package org.dcm4chee.conf.upgrade;
import org.dcm4che3.conf.api.internal.DicomConfigurationManager;
import org.dcm4che3.conf.api.upgrade.ConfigurationMetadata;
import org.dcm4che3.conf.core.api.ConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PassiveUpgrade
{
private static Logger log = LoggerFactory.getLogger(PassiveUpgrade.class);
public static final String PASSIVE_UPGRADE_TIMEOUT = "org.dcm4che.conf.upgrade.passiveTimeoutSec";
private final DicomConfigurationManager dicomConfigurationManager;
private final UpgradeSettings upgradeSettings;
private final String appName;
public PassiveUpgrade( DicomConfigurationManager dicomConfigurationManager,
UpgradeSettings upgradeSettings, String appName )
{
this.dicomConfigurationManager = dicomConfigurationManager;
this.upgradeSettings = upgradeSettings;
this.appName = appName;
}
public void waitUntilOtherRunnerUpdatesToTargetConfigurationVersion() {
Integer timeout, configuredTimeout;
try {
configuredTimeout = timeout = Integer.valueOf(System.getProperty(PASSIVE_UPGRADE_TIMEOUT, "300"));
} catch (NumberFormatException e) {
throw new RuntimeException(PASSIVE_UPGRADE_TIMEOUT + " property must be an integer", e);
}
log.info("This deployment (" + appName + ") is not configured to perform the configuration upgrade." +
" Waiting for the upgrade to be performed by deployment '" + upgradeSettings.getActiveUpgradeRunnerDeployment() + "'." +
"\nTimeout: " + configuredTimeout + " sec" +
"\nExpected configuration version: " + upgradeSettings.getUpgradeToVersion());
boolean success = false;
while (timeout > 0) {
try {
ConfigurationMetadata configurationMetadata = dicomConfigurationManager
.getTypeSafeConfiguration()
.load( DicomConfigurationManager.METADATA_ROOT_PATH, ConfigurationMetadata.class );
if (configurationMetadata != null && configurationMetadata.getVersion() != null &&
configurationMetadata.getVersion().equals(upgradeSettings.getUpgradeToVersion())) {
success = true;
/*
* From infinispan wiki:
* Infinispan does not support Snapshot isolation or Read Atomic isolation :
* if a transaction T1 writes K1 and K2, an overlapping transaction T2 may see both K1 and K2, only K1, only K2, or neither.
*
* => we need to avoid hitting a gap in visibility of different cache entries in infinispan,
* i.e. when metadata is already updated but some devices are not yet visible
*
* Reproduced with tests including cluster, observed gap 10-50ms
* Workaround until a better solution found, 5 sec to be on the safe side
*/
Thread.sleep(5000);
break;
}
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
timeout--;
}
if (!success)
throw new ConfigurationException("Waited for " + configuredTimeout + " sec, but configuration was not updated to target version ('" + upgradeSettings.getUpgradeToVersion() + "')." +
"Configuration will not be initialized.");
else
log.info("Detected the expected configuration version ('{}'), proceeding", upgradeSettings.getUpgradeToVersion());
}
}