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.
*
* @return The case name transformed into a corresponding PostgreSQL
* case database name.
* @return The case name transformed into a corresponding PostgreSQL case
* database name.
*/
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.
*
@ -1679,37 +1654,30 @@ public class Case {
open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator);
} else {
/*
* First, acquire an exclusive case name lock to prevent two
* nodes from creating the same case at the same time.
* 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.
*/
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);
/*
* Finally, acquire an exclusive case resources lock to
* ensure only one node at a time can
* create/open/upgrade/close the case resources.
*/
try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(caseName)) {
assert (null != resourcesLock);
try {
open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator);
} catch (CaseActionException ex) {
/*
* Release the case directory lock immediately if
* there was a problem opening the case.
*/
if (CaseType.MULTI_USER_CASE == caseType) {
releaseSharedCaseDirLock(caseName);
}
throw ex;
acquireSharedCaseDirLock(caseDir);
/*
* Acquire an exclusive case resources lock to ensure only one
* node at a time can create/open/upgrade/close the case
* resources.
*/
try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(caseName)) {
assert (null != resourcesLock);
try {
open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator);
} catch (CaseActionException ex) {
/*
* Release the case directory lock immediately if there
* was a problem opening the case.
*/
if (CaseType.MULTI_USER_CASE == caseType) {
releaseSharedCaseDirLock(caseName);
}
throw ex;
}
}
}

View File

@ -1932,38 +1932,50 @@ 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()});
currentJob.setStage(AutoIngestJob.Stage.OPENING_CASE);
try {
Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, caseName);
if (null != caseDirectoryPath) {
Path metadataFilePath = caseDirectoryPath.resolve(caseName + CaseMetadata.getFileExtension());
Case.openAsCurrentCase(metadataFilePath.toString());
} else {
caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName);
Case.createAsCurrentCase(caseDirectoryPath.toString(), caseName, "", "", CaseType.MULTI_USER_CASE);
/*
* Sleep a bit before releasing the lock to ensure that the
* new case folder is visible on the network.
*/
Thread.sleep(AutoIngestUserPreferences.getSecondsToSleepBetweenCases() * 1000);
}
currentJob.setCaseDirectoryPath(caseDirectoryPath);
Case caseForJob = Case.getCurrentCase();
SYS_LOGGER.log(Level.INFO, "Opened case {0} for {1}", new Object[]{caseForJob.getName(), manifest.getFilePath()});
return caseForJob;
/*
* 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 {
Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, caseName);
if (null != caseDirectoryPath) {
Path metadataFilePath = caseDirectoryPath.resolve(caseName + CaseMetadata.getFileExtension());
Case.openAsCurrentCase(metadataFilePath.toString());
} else {
caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName);
Case.createAsCurrentCase(caseDirectoryPath.toString(), caseName, "", "", CaseType.MULTI_USER_CASE);
/*
* Sleep a bit before releasing the lock to ensure
* that the new case folder is visible on the
* network.
*/
Thread.sleep(AutoIngestUserPreferences.getSecondsToSleepBetweenCases() * 1000);
}
currentJob.setCaseDirectoryPath(caseDirectoryPath);
Case caseForJob = Case.getCurrentCase();
SYS_LOGGER.log(Level.INFO, "Opened case {0} for {1}", new Object[]{caseForJob.getName(), manifest.getFilePath()});
return caseForJob;
} catch (CaseActionException ex) {
throw new CaseManagementException(String.format("Error creating or opening case %s (%s) for %s", manifest.getCaseName(), caseName, manifest.getFilePath()), ex);
} catch (IllegalStateException ex) {
/*
* Deal with the unfortunate fact that Case.getCurrentCase
* throws IllegalStateException.
*/
throw new CaseManagementException(String.format("Error getting current case %s (%s) for %s", caseName, manifest.getCaseName(), manifest.getFilePath()), ex);
} catch (CaseActionException ex) {
throw new CaseManagementException(String.format("Error creating or opening case %s (%s) for %s", manifest.getCaseName(), caseName, manifest.getFilePath()), ex);
} catch (IllegalStateException ex) {
/*
* Deal with the unfortunate fact that
* Case.getCurrentCase throws IllegalStateException.
*/
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.
*