Skip to content
Snippets Groups Projects
Commit 56606597 authored by anttil's avatar anttil
Browse files

SSDM-4003: New DSS FS (FTP / CIFS) resolvers: implemented a short-lived cache for resolve requests.

SVN: 36887
parent c09d3ee5
No related branches found
No related tags found
No related merge requests found
......@@ -23,9 +23,10 @@ import java.util.Map;
import org.apache.ftpserver.ftplet.FtpFile;
import ch.systemsx.cisd.common.utilities.ITimeProvider;
import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpFile;
import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
/**
* Helper class to cache objects retrieved from remote services. Used by {@link FtpPathResolverContext}.
......@@ -48,13 +49,13 @@ public class Cache
this.timestamp = timestamp;
}
}
private final Map<String, TimeStampedObject<FtpFile>> filesByPath = new HashMap<>();
private final Map<String, TimeStampedObject<DataSet>> dataSetsByCode = new HashMap<String, Cache.TimeStampedObject<DataSet>>();
private final Map<String, TimeStampedObject<List<AbstractExternalData>>> dataSetsByExperiment = new HashMap<>();
private final Map<String, TimeStampedObject<AbstractExternalData>> externalData =
new HashMap<String, Cache.TimeStampedObject<AbstractExternalData>>();
......@@ -62,26 +63,28 @@ public class Cache
private final ITimeProvider timeProvider;
private final Map<String, TimeStampedObject<V3FtpFile>> v3Responses = new HashMap<>();
public Cache(ITimeProvider timeProvider)
{
this.timeProvider = timeProvider;
}
void putFile(FtpFile file, String path)
{
filesByPath.put(path, timestamp(file));
}
FtpFile getFile(String path)
{
return getObject(filesByPath, path);
}
void putDataSetsForExperiment(List<AbstractExternalData> dataSets, String experimentPermId)
{
dataSetsByExperiment.put(experimentPermId, timestamp(dataSets));
}
List<AbstractExternalData> getDataSetsByExperiment(String experimentPermId)
{
return getObject(dataSetsByExperiment, experimentPermId);
......@@ -117,6 +120,16 @@ public class Cache
experiments.put(experiment.getIdentifier(), timestamp(experiment));
}
public V3FtpFile getResponse(String key)
{
return getObject(v3Responses, key);
}
public void putResponse(String key, V3FtpFile file)
{
v3Responses.put(key, timestamp(file));
}
private <T> TimeStampedObject<T> timestamp(T object)
{
return new TimeStampedObject<T>(object, timeProvider.getTimeInMilliseconds());
......@@ -127,7 +140,7 @@ public class Cache
TimeStampedObject<T> timeStampedObject = map.get(key);
return timeStampedObject == null
|| timeProvider.getTimeInMilliseconds() - timeStampedObject.timestamp > LIVE_TIME ? null
: timeStampedObject.object;
: timeStampedObject.object;
}
}
\ No newline at end of file
......@@ -27,10 +27,12 @@ import org.apache.log4j.Logger;
import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
import ch.systemsx.cisd.openbis.dss.generic.server.ftp.Cache;
import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverConfig;
import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverContext;
import ch.systemsx.cisd.openbis.dss.generic.server.ftp.IFtpPathResolverRegistry;
import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpDirectoryResponse;
import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpFile;
import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpNonExistingFile;
import ch.systemsx.cisd.openbis.dss.generic.shared.Constants;
......@@ -80,35 +82,50 @@ public class V3FtpPathResolverRegistry implements IFtpPathResolverRegistry
}
}
// note to self - the resolver context is created fresh for each request
@Override
public FtpFile resolve(String path, FtpPathResolverContext resolverContext)
{
System.err.println(path + " Resolver registry: " + this.hashCode());
String responseCacheKey = resolverContext.getSessionToken() + "$" + path;
Cache cache = resolverContext.getCache();
V3FtpFile response = cache.getResponse(responseCacheKey);
if (response != null)
{
operationLog.info("Path "+path+" requested (found in cache).");
return response;
}
operationLog.info("Path "+path+" requested.");
String[] split = path.equals("/") ? new String[] {} : path.substring(1).split("/");
try
{
if (plugins.size() > 0)
{
return resolvePlugins(path, split, resolverContext);
response = resolvePlugins(path, split, resolverContext);
} else
{
return resolveDefault(path, resolverContext, split);
response = resolveDefault(path, resolverContext, split);
}
} catch (Exception e)
{
operationLog.warn("Resolving "+path+" failed", e);
operationLog.warn("Resolving " + path + " failed", e);
response = new V3FtpNonExistingFile(path, "Error when retrieving path");
}
return new V3FtpNonExistingFile(path, "Error when retrieving path");
cache.putResponse(responseCacheKey, response);
return response;
}
private FtpFile resolveDefault(String path, FtpPathResolverContext resolverContext, String[] split)
private V3FtpFile resolveDefault(String path, FtpPathResolverContext resolverContext, String[] split)
{
V3RootLevelResolver resolver = new V3RootLevelResolver();
return resolver.resolve(path, split, resolverContext);
}
private FtpFile resolvePlugins(String path, String[] subPath, FtpPathResolverContext resolverContext)
private V3FtpFile resolvePlugins(String path, String[] subPath, FtpPathResolverContext resolverContext)
{
if (subPath.length == 0)
{
......
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