From 0a563da05e7ae3ed40a25912528e1ad1cf07e4a7 Mon Sep 17 00:00:00 2001 From: anttil <anttil> Date: Thu, 11 Aug 2016 13:40:17 +0000 Subject: [PATCH] SSDM-4003: New DSS FS (FTP / CIFS) resolvers: More caching, fix bug with CIFS session breaking on unavailable file SVN: 36897 --- .../server/cifs/DSSFileSearchContext.java | 8 ++--- .../generic/server/cifs/DataSetCifsView.java | 15 +++++++--- .../openbis/dss/generic/server/ftp/Cache.java | 25 ++++++++++++++++ .../ftp/v3/V3DataSetContentResolver.java | 29 +++++++++++++++---- 4 files changed, 61 insertions(+), 16 deletions(-) diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/cifs/DSSFileSearchContext.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/cifs/DSSFileSearchContext.java index 49a0a348a00..24c4326a82c 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/cifs/DSSFileSearchContext.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/cifs/DSSFileSearchContext.java @@ -40,7 +40,7 @@ public class DSSFileSearchContext extends SearchContext private int index; - public DSSFileSearchContext(DSSFileSystemView view, String normalizedSearchPath, int fileAttributes, + public DSSFileSearchContext(DSSFileSystemView view, String normalizedSearchPath, int fileAttributes, Cache cache) throws FileNotFoundException { String[] pathStr = FileName.splitPath(normalizedSearchPath, java.io.File.separatorChar); @@ -77,7 +77,7 @@ public class DSSFileSearchContext extends SearchContext FtpFile file = view.getFile(path, cache); if (file instanceof NonExistingFtpFile) { - throw new FtpException(file.getAbsolutePath() + " doesn't exist. Reason: " + throw new FtpException(file.getAbsolutePath() + " doesn't exist. Reason: " + ((NonExistingFtpFile) file).getErrorMessage()); } return file; @@ -114,8 +114,6 @@ public class DSSFileSearchContext extends SearchContext @Override public String nextFileName() { - System.out.println("DSSFileSearchContext.nextFileName()"); - // TODO Auto-generated method stub return null; } @@ -133,8 +131,6 @@ public class DSSFileSearchContext extends SearchContext @Override public boolean restartAt(FileInfo info) { - System.out.println("DSSFileSearchContext.restartAt() "+info); - // TODO Auto-generated method stub return false; } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/cifs/DataSetCifsView.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/cifs/DataSetCifsView.java index 392f9ddbe5b..23942db5f66 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/cifs/DataSetCifsView.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/cifs/DataSetCifsView.java @@ -30,6 +30,7 @@ import org.alfresco.jlan.server.filesys.DiskInterface; import org.alfresco.jlan.server.filesys.FileAttribute; import org.alfresco.jlan.server.filesys.FileInfo; import org.alfresco.jlan.server.filesys.FileName; +import org.alfresco.jlan.server.filesys.FileOfflineException; import org.alfresco.jlan.server.filesys.FileOpenParams; import org.alfresco.jlan.server.filesys.FileStatus; import org.alfresco.jlan.server.filesys.NetworkFile; @@ -226,12 +227,18 @@ public class DataSetCifsView implements DiskInterface } operationLog.debug("Read from virtual file '" + file.getFullName() + "' at position " + filePos + " " + size + " bytes into the buffer of size " + buf.length + " at position " + bufPos + "."); - int rdlen = file.readFile(buf, size, bufPos, filePos); - if (rdlen == -1) + try + { + int rdlen = file.readFile(buf, size, bufPos, filePos); + if (rdlen == -1) + { + rdlen = 0; + } + return rdlen; + } catch (RuntimeException e) { - rdlen = 0; + throw new FileOfflineException(); } - return rdlen; } @Override 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 5f428676c31..4ad07497625 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,6 +23,7 @@ import java.util.Map; import org.apache.ftpserver.ftplet.FtpFile; import ch.systemsx.cisd.common.utilities.ITimeProvider; +import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchicalContent; 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.AbstractExternalData; @@ -65,6 +66,10 @@ public class Cache private final Map<String, TimeStampedObject<V3FtpFile>> v3Responses = new HashMap<>(); + private final Map<String, TimeStampedObject<IHierarchicalContent>> contents = new HashMap<>(); + + private final Map<String, TimeStampedObject<Boolean>> accessData = new HashMap<>(); + public Cache(ITimeProvider timeProvider) { this.timeProvider = timeProvider; @@ -130,6 +135,26 @@ public class Cache v3Responses.put(key, timestamp(file)); } + public IHierarchicalContent getContent(String key) + { + return getObject(contents, key); + } + + public void putContent(String key, IHierarchicalContent content) + { + contents.put(key, timestamp(content)); + } + + public Boolean getAccess(String dataSetCode) + { + return getObject(accessData, dataSetCode); + } + + public void putAccess(String dataSetCode, Boolean access) + { + accessData.put(dataSetCode, timestamp(access)); + } + private <T> TimeStampedObject<T> timestamp(T object) { return new TimeStampedObject<T>(object, timeProvider.getTimeInMilliseconds()); diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3DataSetContentResolver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3DataSetContentResolver.java index 212ea49ce4b..2e6fa6cdfb9 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3DataSetContentResolver.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3DataSetContentResolver.java @@ -24,6 +24,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetFetc import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.DataSetPermId; import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.IDataSetId; import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchicalContent; +import ch.systemsx.cisd.openbis.dss.generic.server.ftp.Cache; import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverContext; import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpFile; import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpNonExistingFile; @@ -45,17 +46,33 @@ public class V3DataSetContentResolver implements V3Resolver @Override public V3FtpFile resolve(String fullPath, String[] subPath, FtpPathResolverContext context) { - // this fetching of data set is for authorization purposes, as content provider doesn't check if user has access to data set - IDataSetId id = new DataSetPermId(dataSetCode); - Map<IDataSetId, DataSet> dataSets = - context.getV3Api().getDataSets(context.getSessionToken(), Collections.singletonList(id), new DataSetFetchOptions()); + Cache cache = context.getCache(); - if (dataSets.get(id) == null) + Boolean hasAccess = cache.getAccess(dataSetCode); + if (hasAccess == null) + { + + // this fetching of data set is for authorization purposes, as content provider doesn't check if user has access to data set + IDataSetId id = new DataSetPermId(dataSetCode); + Map<IDataSetId, DataSet> dataSets = + context.getV3Api().getDataSets(context.getSessionToken(), Collections.singletonList(id), new DataSetFetchOptions()); + + hasAccess = dataSets.containsKey(id); + cache.putAccess(dataSetCode, hasAccess); + } + + if (hasAccess.booleanValue() == false) { return new V3FtpNonExistingFile(fullPath, "Path doesn't exist or unauthorized"); } - IHierarchicalContent content = context.getContentProvider().asContent(dataSetCode); + IHierarchicalContent content = cache.getContent(dataSetCode); + if (content == null) + { + content = context.getContentProvider().asContentWithoutModifyingAccessTimestamp(dataSetCode); + cache.putContent(dataSetCode, content); + } + V3HierarchicalContentResolver resolver = new V3HierarchicalContentResolver(content); return resolver.resolve(fullPath, subPath, context); } -- GitLab