Skip to content
Snippets Groups Projects
Commit e17062f7 authored by juanf's avatar juanf
Browse files

SSDM-5407 : New Write / Atomic move test on dss startup

SVN: 38582
parent f4c8e743
No related branches found
No related tags found
No related merge requests found
...@@ -17,6 +17,10 @@ ...@@ -17,6 +17,10 @@
package ch.systemsx.cisd.openbis.dss.generic.shared.utils; package ch.systemsx.cisd.openbis.dss.generic.shared.utils;
import java.io.File; import java.io.File;
import java.nio.file.FileStore;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -97,8 +101,15 @@ public class DssPropertyParametersUtil ...@@ -97,8 +101,15 @@ public class DssPropertyParametersUtil
private static final Template NON_EXISTING_DIR_TEMPLATE = new Template( private static final Template NON_EXISTING_DIR_TEMPLATE = new Template(
"Could not create ${dir-description} at path: ${path}. " + EXPLANATION); "Could not create ${dir-description} at path: ${path}. " + EXPLANATION);
private static final Template NON_LOCAL_DIR_TEMPLATE = new Template( private static final Template NON_SAME_VOLUME_TEMPLATE = new Template(
"Directory at path '${path}' is not on the local file system. " + EXPLANATION); "Directories '${pathA}', '${pathB}', '${pathC}' are not on the same file system. ");
private static final Template NON_WRITABLE_TEMPLATE = new Template(
"Directory '${pathA}' is not writable. ");
private static final Template NON_VOLUME_TEMPLATE = new Template("Volume information for '${volA}' is not retrivable. ");
private static final Template NON_MOVE_TEMPLATE = new Template("Move operation failed from '${pathA}' to '${pathB}'. ");
/** loads server configuration */ /** loads server configuration */
public static ExtendedProperties loadServiceProperties() public static ExtendedProperties loadServiceProperties()
...@@ -203,6 +214,7 @@ public class DssPropertyParametersUtil ...@@ -203,6 +214,7 @@ public class DssPropertyParametersUtil
@Private @Private
static File getDssInternalTempDir(IFileOperations fileOperations, final Properties properties) static File getDssInternalTempDir(IFileOperations fileOperations, final Properties properties)
{ {
createAndTestSpecialDirectories(fileOperations, properties);
return getDir(fileOperations, properties, "dss-tmp", return getDir(fileOperations, properties, "dss-tmp",
"an internal temp directory for the data store server", DSS_TEMP_DIR_PATH); "an internal temp directory for the data store server", DSS_TEMP_DIR_PATH);
} }
...@@ -215,6 +227,7 @@ public class DssPropertyParametersUtil ...@@ -215,6 +227,7 @@ public class DssPropertyParametersUtil
@Private @Private
static File getDssRegistrationLogDir(IFileOperations fileOperations, final Properties properties) static File getDssRegistrationLogDir(IFileOperations fileOperations, final Properties properties)
{ {
createAndTestSpecialDirectories(fileOperations, properties);
return getDir(fileOperations, properties, "log-registrations", return getDir(fileOperations, properties, "log-registrations",
"a directory for storing registration logs", DSS_REGISTRATION_LOG_DIR_PATH); "a directory for storing registration logs", DSS_REGISTRATION_LOG_DIR_PATH);
} }
...@@ -227,12 +240,13 @@ public class DssPropertyParametersUtil ...@@ -227,12 +240,13 @@ public class DssPropertyParametersUtil
@Private @Private
static File getDssRecoveryStateDir(IFileOperations fileOperations, final Properties properties) static File getDssRecoveryStateDir(IFileOperations fileOperations, final Properties properties)
{ {
return getDir(fileOperations, properties, "recovery-state", createAndTestSpecialDirectories(fileOperations, properties);
"a directory for storing recovery state for the dss", DSS_RECOVERY_STATE_DIR_PATH); return getDir(fileOperations, properties, "recovery-state", "a directory for storing recovery state for the dss",
DSS_RECOVERY_STATE_DIR_PATH);
} }
private static File getDir(IFileOperations fileOperations, final Properties properties, private static File getDir(IFileOperations fileOperations, final Properties properties, String defaultDirName, String dirDescription,
String defaultDirName, String dirDescription, String pathKey) String pathKey)
{ {
String defaultRegistrationLogDirPath = String defaultRegistrationLogDirPath =
new File(System.getProperty("user.dir"), defaultDirName).getAbsolutePath(); new File(System.getProperty("user.dir"), defaultDirName).getAbsolutePath();
...@@ -240,41 +254,111 @@ public class DssPropertyParametersUtil ...@@ -240,41 +254,111 @@ public class DssPropertyParametersUtil
PropertyUtils.getProperty(properties, pathKey, defaultRegistrationLogDirPath); PropertyUtils.getProperty(properties, pathKey, defaultRegistrationLogDirPath);
File registrationLogDir = new File(registrationLogDirPath); File registrationLogDir = new File(registrationLogDirPath);
fileOperations.mkdirs(registrationLogDir); fileOperations.mkdirs(registrationLogDir);
assertDirExistsAndIsLocal(fileOperations, registrationLogDir, dirDescription, pathKey); assertDirExists(fileOperations, registrationLogDir, dirDescription, pathKey);
return registrationLogDir; return registrationLogDir;
} }
private static AtomicInteger atomicEmptyFileIndex = new AtomicInteger(); private static AtomicInteger atomicEmptyFileIndex = new AtomicInteger();
private static void assertDirExistsAndIsLocal(IFileOperations fileOperations, File dir, private static boolean isWritable(IFileOperations fileOperations, Path path)
String dirDescription, String pathKey)
{ {
String threadSafeEmptyTestFileName = EMPTY_TEST_FILE_NAME + atomicEmptyFileIndex.incrementAndGet(); boolean created = false;
File threadSafeEmptyTestFile = null; File file = null;
File emptyTestFileInDir = null; try
{
String threadSafeEmptyTestFileName = EMPTY_TEST_FILE_NAME + atomicEmptyFileIndex.incrementAndGet();
file = Paths.get(path.toString(), threadSafeEmptyTestFileName).toFile();
created = fileOperations.createNewFile(file);
} catch (Exception ex)
{
created = false;
} finally
{
if (created && file != null)
{
fileOperations.delete(file);
}
}
return created;
}
private static FileStore getVolumeInfo(Path path, String key)
{
FileStore info = null;
try try
{ {
assertDirExists(fileOperations, dir, dirDescription, pathKey); info = Files.getFileStore(path);
threadSafeEmptyTestFile = new File(threadSafeEmptyTestFileName); } catch (Exception ex)
fileOperations.createNewFile(threadSafeEmptyTestFile); {
emptyTestFileInDir = new File(dir, threadSafeEmptyTestFileName); createException(NON_VOLUME_TEMPLATE, key);
if (fileOperations.rename(threadSafeEmptyTestFile, emptyTestFileInDir) == false) }
return info;
}
private static boolean isMoveFromTo(IFileOperations fileOperations, Path pathA, Path pathB)
{
boolean created = false;
boolean moved = false;
File originalfile = null;
File toMove = null;
try
{
String threadSafeEmptyTestFileName = EMPTY_TEST_FILE_NAME + atomicEmptyFileIndex.incrementAndGet();
originalfile = Paths.get(pathA.toString(), threadSafeEmptyTestFileName).toFile();
created = fileOperations.createNewFile(originalfile);
if (created)
{ {
throw createException(NON_LOCAL_DIR_TEMPLATE.createFreshCopy(), dir, toMove = Paths.get(pathB.toString(), threadSafeEmptyTestFileName).toFile();
dirDescription, pathKey); fileOperations.move(originalfile, toMove);
moved = true;
} }
} catch (Exception ex)
{
moved = false;
} finally } finally
{ {
if (threadSafeEmptyTestFile != null) if (moved && toMove != null)
{
fileOperations.delete(toMove);
} else if (created && originalfile != null)
{ {
fileOperations.delete(threadSafeEmptyTestFile); fileOperations.delete(originalfile);
} }
if (emptyTestFileInDir != null) }
return moved;
}
private static void createAndTestSpecialDirectories(IFileOperations fileOperations, final Properties properties)
{
Path dssTmp = getDir(fileOperations, properties, "dss-tmp", "an internal temp directory for the data store server", DSS_TEMP_DIR_PATH)
.toPath();
Path recoveryState = getDir(fileOperations, properties, "recovery-state", "a directory for storing recovery state for the dss",
DSS_RECOVERY_STATE_DIR_PATH).toPath();
Path logRegistrations = getDir(fileOperations, properties, "log-registrations", "a directory for storing registration logs",
DSS_REGISTRATION_LOG_DIR_PATH).toPath();
FileStore dssTmpStore = getVolumeInfo(dssTmp, "dss-tmp");
FileStore recoveryStateStore = getVolumeInfo(dssTmp, "recovery-state");
FileStore logRegistrationsState = getVolumeInfo(dssTmp, "log-registrations");
if (dssTmpStore.equals(recoveryStateStore) && recoveryStateStore.equals(logRegistrationsState)) // Check they are on the same Volume
{
if (!isWritable(fileOperations, dssTmp))
{
throw createException(NON_WRITABLE_TEMPLATE, dssTmp);
} else if (!isMoveFromTo(fileOperations, dssTmp, recoveryState))
{ {
fileOperations.delete(emptyTestFileInDir); throw createException(NON_MOVE_TEMPLATE, dssTmp, recoveryState);
} else if (!isMoveFromTo(fileOperations, dssTmp, logRegistrations))
{
throw createException(NON_MOVE_TEMPLATE, dssTmp, logRegistrations);
} }
} else
{
throw createException(NON_SAME_VOLUME_TEMPLATE, dssTmp, recoveryState, logRegistrations);
} }
} }
private static void assertDirExists(IFileOperations fileOperations, File dir, private static void assertDirExists(IFileOperations fileOperations, File dir,
...@@ -287,6 +371,38 @@ public class DssPropertyParametersUtil ...@@ -287,6 +371,38 @@ public class DssPropertyParametersUtil
} }
} }
private static ConfigurationFailureException createException(Template template, Path pathA, Path pathB)
{
template.bind("pathA", pathA.toString());
template.bind("pathB", pathB.toString());
ConfigurationFailureException e = new ConfigurationFailureException(template.createText());
return e;
}
private static ConfigurationFailureException createException(Template template, String volumeA)
{
template.bind("volA", volumeA);
ConfigurationFailureException e = new ConfigurationFailureException(template.createText());
return e;
}
private static ConfigurationFailureException createException(Template template, Path pathA)
{
template.bind("pathA", pathA.toString());
ConfigurationFailureException e = new ConfigurationFailureException(template.createText());
return e;
}
private static ConfigurationFailureException createException(Template template, Path pathA,
Path pathB, Path pathC)
{
template.bind("pathA", pathA.toString());
template.bind("pathB", pathB.toString());
template.bind("pathB", pathC.toString());
ConfigurationFailureException e = new ConfigurationFailureException(template.createText());
return e;
}
private static ConfigurationFailureException createException(Template template, File dir, private static ConfigurationFailureException createException(Template template, File dir,
String dirName, String pathKey) String dirName, String pathKey)
{ {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment