From 56606597c25e3e41095998b5b971db567dfcd94f Mon Sep 17 00:00:00 2001 From: anttil <anttil> Date: Tue, 9 Aug 2016 13:22:01 +0000 Subject: [PATCH] SSDM-4003: New DSS FS (FTP / CIFS) resolvers: implemented a short-lived cache for resolve requests. SVN: 36887 --- .../openbis/dss/generic/server/ftp/Cache.java | 29 +++++++++++----- .../ftp/v3/V3FtpPathResolverRegistry.java | 33 ++++++++++++++----- 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/Cache.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/Cache.java index a03bd96f9ee..5f428676c31 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/Cache.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/Cache.java @@ -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 diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3FtpPathResolverRegistry.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3FtpPathResolverRegistry.java index ff4da3517c5..71bd571d3b2 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3FtpPathResolverRegistry.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3FtpPathResolverRegistry.java @@ -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) { -- GitLab