/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.instancemanagement.internal;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
* Decorator for centralising synchronization of
* {@link InstanceOperationsImpl#startInstanceUsingInstallation(java.util.List, java.io.File, long)} and
* {@link InstanceOperationsImpl#shutdownInstance(java.util.List, long)}.
*
* @author David Scholz
*/
public final class InstanceOperationsImplSynchronizeDecorator extends AbstractInstanceOperationsDecorator {
private Map<String, File> profileNameToProfileFileObjectMap = new ConcurrentHashMap<>();
private Map<String, AtomicInteger> profileToCounterObjectMap = new ConcurrentHashMap<String, AtomicInteger>();
public InstanceOperationsImplSynchronizeDecorator(InstanceOperations delegate) {
super(delegate);
registerInstanceOperationCallbackListener(new InstanceOperationCallbackListener() {
@Override
public void onCommandFinish(File profile) throws IOException {
synchronized (profileNameToProfileFileObjectMap) {
if (profileToCounterObjectMap.get(profile.getName()).getAndDecrement() == 0) {
profileNameToProfileFileObjectMap.remove(profile.getName());
}
}
}
});
}
/**
*
* Delegates to {@link InstanceOperationsImplReleaseLockDecorator#startInstanceUsingInstallation(List, File, long)} and synchronizes
* thread access with the profile file objects. They are deleted after {@link InstanceOperationCallbackListener#onCommandFinish(File)}
* is called.
*
* @param profileDirList profileDirList the profiles to start.
* @param installationDir the installation directory of the instance installation.
* @param timeout the maximum time this job is allowed to take.
* @throws InstanceOperationException on failure.
*/
@Override
public void beforeStart(List<File> profileDirList, File installationDir, long timeout) throws InstanceOperationException {
synchronized (profileNameToProfileFileObjectMap) {
for (File profileDir : new ArrayList<>(profileDirList)) {
if (profileNameToProfileFileObjectMap.containsKey(profileDir.getName())) {
profileDirList.remove(profileDir);
profileDirList.add(profileNameToProfileFileObjectMap.get(profileDir.getName()));
profileToCounterObjectMap.get(profileDir.getName()).incrementAndGet();
} else {
profileNameToProfileFileObjectMap.put(profileDir.getName(), profileDir);
profileToCounterObjectMap.put(profileDir.getName(), new AtomicInteger(1));
}
}
}
}
/**
*
* Delegates to {@link InstanceOperationsImplReleaseLockDecorator#startInstanceUsingInstallation(List, File, long)} and synchronizes
* thread access with the profile file objects. They are destroyed after {@link InstanceOperationCallbackListener#onCommandFinish(File)}
* is called.
*
* @param profileDirList profileDirList the profiles to start.
* @param timeout the maximum time this job is allowed to take.
* @throws InstanceOperationException on failure
*/
@Override
public void beforeShutdown(List<File> profileDirList, long timeout) throws InstanceOperationException {
synchronized (profileNameToProfileFileObjectMap) {
for (File profileDir : new ArrayList<>(profileDirList)) {
if (profileNameToProfileFileObjectMap.containsKey(profileDir.getName())) {
profileDirList.remove(profileDir);
profileDirList.add(profileNameToProfileFileObjectMap.get(profileDir.getName()));
profileToCounterObjectMap.get(profileDir.getName()).decrementAndGet();
} else {
profileNameToProfileFileObjectMap.put(profileDir.getName(), profileDir);
profileNameToProfileFileObjectMap.put(profileDir.getName(), profileDir);
profileToCounterObjectMap.put(profileDir.getName(), new AtomicInteger(1));
}
}
}
}
@Override
public void onStartupFailure(List<File> profileDirList) {
synchronized (profileNameToProfileFileObjectMap) {
for (File failedInstance : profileDirList) {
profileNameToProfileFileObjectMap.remove(failedInstance.getName());
}
}
}
@Override
public void onShutdownFailure(List<File> profileDirList) {
synchronized (profileNameToProfileFileObjectMap) {
for (File failedInstance : profileDirList) {
profileNameToProfileFileObjectMap.remove(failedInstance.getName());
}
}
}
}