/*
* Copyright (c) 2012 Diamond Light Source Ltd.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package uk.ac.diamond.scisoft.analysis.io.emulated;
import org.eclipse.dawnsci.analysis.api.io.IDataHolder;
import org.eclipse.dawnsci.analysis.api.io.IFileLoader;
import org.eclipse.dawnsci.analysis.api.io.ScanFileHolderException;
import org.eclipse.january.IMonitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An implementation of {@link IFileLoader} that wraps a 'real' loader to emulate the latency of file availability and load time.
*/
public class FileSystemEmulatingFileLoader implements IFileLoader {
transient private static final Logger logger = LoggerFactory.getLogger(FileSystemEmulatingFileLoader.class);
private final IFileLoader loader;
private long emulatedFileAvailableTimeMillis;
private final long emulatedFileLoadTimeMillis;
/**
* Creates a FileSystem emulator that wraps a real {@link IFileLoader} loader.
* @param loader the real loader to wrap
* @param emulatedFileAvailabilityLatencyMillis
* @param emulatedFileLoadTimeMillis
*/
public FileSystemEmulatingFileLoader(IFileLoader loader, long emulatedFileAvailabilityLatencyMillis,
long emulatedFileLoadTimeMillis) {
this.loader = loader;
this.emulatedFileLoadTimeMillis = emulatedFileLoadTimeMillis;
long currentTimeMillis = System.currentTimeMillis();
emulatedFileAvailableTimeMillis = currentTimeMillis + emulatedFileAvailabilityLatencyMillis;
}
@Override
public IDataHolder loadFile() throws ScanFileHolderException {
waitForFileAvailable();
long loadStartTime = System.currentTimeMillis();
IDataHolder loadedFile = loader.loadFile();
waitForFileLoaded(loadStartTime);
return loadedFile;
}
@Override
public IDataHolder loadFile(IMonitor mon) throws ScanFileHolderException {
waitForFileAvailable();
long loadStartTime = System.currentTimeMillis();
IDataHolder loadedFile = loader.loadFile(mon);
waitForFileLoaded(loadStartTime);
return loadedFile;
}
private void waitForFileAvailable() throws ScanFileHolderException {
try {
sleepUntil(emulatedFileAvailableTimeMillis);
} catch (InterruptedException e) {
throw new ScanFileHolderException("Interupted while sleeping to emulate file availability", e);
}
}
private void waitForFileLoaded(long fileLoadStartTime) throws ScanFileHolderException {
long physicalLoadDeltaTime = System.currentTimeMillis() - fileLoadStartTime;
if (physicalLoadDeltaTime <= emulatedFileLoadTimeMillis) {
try {
Thread.sleep(emulatedFileLoadTimeMillis - physicalLoadDeltaTime);
} catch (InterruptedException e) {
throw new ScanFileHolderException("Interupted while sleeping to emulate file load time", e);
}
} else {
logger.warn("File took longer to load ({}ms) than the desired emulated time ({}ms)", physicalLoadDeltaTime,emulatedFileLoadTimeMillis);
}
}
private void sleepUntil(long timeMillis) throws InterruptedException {
long sleepForMillis = timeMillis - System.currentTimeMillis();
if (sleepForMillis > 0) {
Thread.sleep(sleepForMillis);
}
}
@Override
public void setLoadMetadata(boolean willLoadMetadata) {
}
@Override
public void setLoadAllLazily(boolean willLoadLazily) {
}
@Override
public void setAsyncLoad(boolean treeOnTop) {
throw new RuntimeException("Asynchronous loadering is not supported!");
}
@Override
public boolean isLoading() {
throw new RuntimeException("Asynchronous loadering is not supported!");
}
}