This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit 307e235827e8717dbe3eda81ae5bf56a1a91de05 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Fri Feb 10 23:30:30 2023 +0100 Fix a performance issue when file reading are monitored in a JavaFX window. It was caused by the "HTTP range" not forwarded by the channel wrapper. --- .../apache/sis/internal/gui/io/FileAccessItem.java | 17 +++++++- .../sis/internal/storage/io/ByteRangeChannel.java | 46 ++++++++++++++++++++++ .../sis/internal/storage/io/ChannelDataInput.java | 4 +- .../internal/storage/io/FileCacheByteChannel.java | 5 ++- 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/io/FileAccessItem.java b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/io/FileAccessItem.java index 328c516af9..15b088352b 100644 --- a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/io/FileAccessItem.java +++ b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/io/FileAccessItem.java @@ -40,6 +40,7 @@ import javafx.util.Duration; import org.apache.sis.measure.Range; import org.apache.sis.internal.util.Numerics; import org.apache.sis.util.collection.RangeSet; +import org.apache.sis.internal.storage.io.ByteRangeChannel; /** @@ -420,7 +421,7 @@ final class FileAccessItem implements Runnable, EventHandler<ActionEvent> { /** * Wrapper around a {@link SeekableByteChannel} which will observe the ranges of bytes read or written. */ - final class Observer implements SeekableByteChannel { + final class Observer extends ByteRangeChannel { /** * The channel doing the actual read or write operations. */ @@ -434,6 +435,20 @@ final class FileAccessItem implements Runnable, EventHandler<ActionEvent> { fileSize = channel.size(); } + /** + * Specifies a range of bytes which is expected to be read. + * This method may do nothing if the backed channel does not support this operation. + * + * @param lower position (inclusive) of the first byte to be requested. + * @param upper position (exclusive) of the last byte to be requested. + */ + @Override + public void rangeOfInterest(final long lower, final long upper) { + if (channel instanceof ByteRangeChannel) { + ((ByteRangeChannel) channel).rangeOfInterest(lower, upper); + } + } + /** * Forwards to the wrapped channel and report the range of bytes read. */ diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ByteRangeChannel.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ByteRangeChannel.java new file mode 100644 index 0000000000..c8e19cd0c7 --- /dev/null +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ByteRangeChannel.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.sis.internal.storage.io; + +import java.nio.channels.SeekableByteChannel; + + +/** + * A byte channel where the range of bytes to read can be specified as a hint. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.4 + * @since 1.4 + */ +public abstract class ByteRangeChannel implements SeekableByteChannel { + /** + * Creates a new channel. + */ + protected ByteRangeChannel() { + } + + /** + * Specifies a range of bytes which is expected to be read. + * The range of bytes is only a hint and may be ignored, depending on subclasses. + * Reading more bytes than specified is okay, only potentially less efficient. + * It is okay for this method to do nothing. + * + * @param lower position (inclusive) of the first byte to be requested. + * @param upper position (exclusive) of the last byte to be requested. + */ + public abstract void rangeOfInterest(long lower, long upper); +} diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java index ec18853ec8..e6d89bcde7 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java @@ -960,10 +960,10 @@ public class ChannelDataInput extends ChannelData { * @param upper position (exclusive) of the last byte to be requested. */ public final void rangeOfInterest(long lower, long upper) { - if (channel instanceof FileCacheByteChannel) { + if (channel instanceof ByteRangeChannel) { lower = Math.addExact(lower, channelOffset); upper = Math.addExact(upper, channelOffset); - ((FileCacheByteChannel) channel).rangeOfInterest(lower, upper); + ((ByteRangeChannel) channel).rangeOfInterest(lower, upper); } } diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/FileCacheByteChannel.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/FileCacheByteChannel.java index 5edbffec53..5fc3577808 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/FileCacheByteChannel.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/FileCacheByteChannel.java @@ -59,7 +59,7 @@ import static org.apache.sis.internal.storage.StoreUtilities.LOGGER; * @version 1.4 * @since 1.4 */ -public abstract class FileCacheByteChannel implements SeekableByteChannel { +public abstract class FileCacheByteChannel extends ByteRangeChannel { /** * Size of the transfer buffer, in number of bytes. */ @@ -488,7 +488,8 @@ public abstract class FileCacheByteChannel implements SeekableByteChannel { * @param lower position (inclusive) of the first byte to be requested. * @param upper position (exclusive) of the last byte to be requested. */ - final synchronized void rangeOfInterest(final long lower, final long upper) { + @Override + public final synchronized void rangeOfInterest(final long lower, final long upper) { if (upper > lower) { rangesOfInterest.add(lower, upper); }