From 1c48060bbcd1a9cb406d16b216d0c2a18c380b79 Mon Sep 17 00:00:00 2001 From: pkupczyk <pkupczyk> Date: Mon, 4 Feb 2013 13:41:35 +0000 Subject: [PATCH] SP-484 / BIS-255 : SFTP problems: "Downloading is very slow and slows down until OutOfMemoryError is thrown. There is also a lot of log activity on the remote DSS" fixed SVN: 28276 --- .../common/io/FullLengthReadingStream.java | 59 ++++++++++ .../io/FullLengthReadingStreamTest.java | 111 ++++++++++++++++++ .../generic/shared/content/ContentCache.java | 3 +- 3 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 common/source/java/ch/systemsx/cisd/common/io/FullLengthReadingStream.java create mode 100644 common/sourceTest/java/ch/systemsx/cisd/common/io/FullLengthReadingStreamTest.java diff --git a/common/source/java/ch/systemsx/cisd/common/io/FullLengthReadingStream.java b/common/source/java/ch/systemsx/cisd/common/io/FullLengthReadingStream.java new file mode 100644 index 00000000000..84c96d44dcd --- /dev/null +++ b/common/source/java/ch/systemsx/cisd/common/io/FullLengthReadingStream.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.common.io; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * A stream decorator that always returns a requested number of bytes even though the decorated + * stream may return this information in smaller chunks (i.e. read method always reads as many bytes + * as were specified by the length parameter unless the end of the stream is reached). + * + * @author pkupczyk + */ +public class FullLengthReadingStream extends FilterInputStream +{ + + public FullLengthReadingStream(InputStream in) + { + super(in); + } + + @Override + public int read(byte[] b, int offset, int length) throws IOException + { + int read = 0; + + while (read < length) + { + int count = in.read(b, offset + read, length - read); + + if (count < 0) + { + return read > 0 ? read : -1; + } else + { + read += count; + } + } + + return read; + } + +} diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/io/FullLengthReadingStreamTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/io/FullLengthReadingStreamTest.java new file mode 100644 index 00000000000..9cdad79b0cc --- /dev/null +++ b/common/sourceTest/java/ch/systemsx/cisd/common/io/FullLengthReadingStreamTest.java @@ -0,0 +1,111 @@ +/* + * Copyright 2013 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.common.io; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +/** + * @author pkupczyk + */ +public class FullLengthReadingStreamTest extends AssertJUnit +{ + + @Test + public void testHalfReadingStream() throws IOException + { + HalfReadingStream stream = new HalfReadingStream(new byte[] + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + + byte[] bytes = new byte[10]; + int count = stream.read(bytes, 3, 11); + + assertEquals(5, count); + assertEquals(new byte[] + { 0, 0, 0, 0, 1, 2, 3, 4, 0, 0 }, bytes); + + bytes = new byte[10]; + count = stream.read(bytes, 8, 4); + + assertEquals(2, count); + assertEquals(new byte[] + { 0, 0, 0, 0, 0, 0, 0, 0, 5, 6 }, bytes); + + bytes = new byte[10]; + count = stream.read(bytes, 0, 10); + + assertEquals(3, count); + assertEquals(new byte[] + { 7, 8, 9, 0, 0, 0, 0, 0, 0, 0 }, bytes); + + bytes = new byte[10]; + count = stream.read(bytes, 0, 10); + + assertEquals(-1, count); + assertEquals(new byte[] + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, bytes); + } + + @Test + public void testFullReadingStream() throws IOException + { + HalfReadingStream stream = new HalfReadingStream(new byte[] + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + FullLengthReadingStream fullStream = new FullLengthReadingStream(stream); + + byte[] bytes = new byte[6]; + int count = fullStream.read(bytes); + + assertEquals(6, count); + assertEquals(new byte[] + { 0, 1, 2, 3, 4, 5 }, bytes); + + bytes = new byte[6]; + count = fullStream.read(bytes); + + assertEquals(4, count); + assertEquals(new byte[] + { 6, 7, 8, 9, 0, 0 }, bytes); + + bytes = new byte[6]; + count = fullStream.read(bytes); + + assertEquals(-1, count); + assertEquals(new byte[] + { 0, 0, 0, 0, 0, 0 }, bytes); + } + + private class HalfReadingStream extends ByteArrayInputStream + { + + public HalfReadingStream(byte[] bytes) + { + super(bytes); + } + + @Override + public int read(byte[] b, int off, int len) + { + return super.read(b, off, Math.max(1, len / 2)); + } + + } + +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/content/ContentCache.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/content/ContentCache.java index 4114cd2e089..643aa182d41 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/content/ContentCache.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/content/ContentCache.java @@ -54,6 +54,7 @@ import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; import ch.systemsx.cisd.common.filesystem.FileOperations; import ch.systemsx.cisd.common.filesystem.FileUtilities; import ch.systemsx.cisd.common.filesystem.IFileOperations; +import ch.systemsx.cisd.common.io.FullLengthReadingStream; import ch.systemsx.cisd.common.logging.LogCategory; import ch.systemsx.cisd.common.logging.LogFactory; import ch.systemsx.cisd.common.properties.PropertyUtils; @@ -461,7 +462,7 @@ public class ContentCache implements IContentCache, InitializingBean try { openStream = url.openStream(); - return openStream; + return new FullLengthReadingStream(openStream); } catch (IOException ex) { IOUtils.closeQuietly(openStream); -- GitLab