This is an automated email from the ASF dual-hosted git repository.
JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git
The following commit(s) were added to refs/heads/master by this push:
new 75f3b93929 [pvfs] Fix double-counted read statistics in VFSInputStream
(#8689)
75f3b93929 is described below
commit 75f3b939296de31989d5217e6727e0ba75357588
Author: Eunbin Son <[email protected]>
AuthorDate: Thu Jul 16 14:12:19 2026 +0900
[pvfs] Fix double-counted read statistics in VFSInputStream (#8689)
---
.../apache/paimon/vfs/hadoop/VFSInputStream.java | 4 +-
.../paimon/vfs/hadoop/VFSInputStreamTest.java | 79 ++++++++++++++++++++++
2 files changed, 80 insertions(+), 3 deletions(-)
diff --git
a/paimon-vfs/paimon-vfs-hadoop/src/main/java/org/apache/paimon/vfs/hadoop/VFSInputStream.java
b/paimon-vfs/paimon-vfs-hadoop/src/main/java/org/apache/paimon/vfs/hadoop/VFSInputStream.java
index f8156554ff..98767254cf 100644
---
a/paimon-vfs/paimon-vfs-hadoop/src/main/java/org/apache/paimon/vfs/hadoop/VFSInputStream.java
+++
b/paimon-vfs/paimon-vfs-hadoop/src/main/java/org/apache/paimon/vfs/hadoop/VFSInputStream.java
@@ -83,9 +83,7 @@ public class VFSInputStream extends FSInputStream {
while ((n = read(oneByteBuf, 0, 1)) == 0) {
/* no op */
}
- if (statistics != null && n >= 0) {
- statistics.incrementBytesRead(n);
- }
+ // read(byte[], int, int) already updated statistics; do not count
again.
return (n == -1) ? -1 : oneByteBuf[0] & 0xff;
}
diff --git
a/paimon-vfs/paimon-vfs-hadoop/src/test/java/org/apache/paimon/vfs/hadoop/VFSInputStreamTest.java
b/paimon-vfs/paimon-vfs-hadoop/src/test/java/org/apache/paimon/vfs/hadoop/VFSInputStreamTest.java
new file mode 100644
index 0000000000..d3747cb0c6
--- /dev/null
+++
b/paimon-vfs/paimon-vfs-hadoop/src/test/java/org/apache/paimon/vfs/hadoop/VFSInputStreamTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.paimon.vfs.hadoop;
+
+import org.apache.paimon.fs.ByteArraySeekableStream;
+
+import org.apache.hadoop.fs.FileSystem;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/** Tests for {@link VFSInputStream}, in particular read-statistics
accounting. */
+public class VFSInputStreamTest {
+
+ @Test
+ public void testSingleByteReadCountsBytesOnce() throws IOException {
+ byte[] content = "hello".getBytes();
+ FileSystem.Statistics stats = new FileSystem.Statistics("pvfs");
+ VFSInputStream stream = new VFSInputStream(new
ByteArraySeekableStream(content), stats);
+
+ byte[] read = new byte[content.length];
+ int n = 0;
+ int b;
+ while ((b = stream.read()) != -1) {
+ read[n++] = (byte) b;
+ }
+ stream.close();
+
+ assertThat(n).isEqualTo(content.length);
+ assertThat(read).isEqualTo(content);
+ // Each byte must be counted exactly once (2N before the fix).
+ assertThat(stats.getBytesRead()).isEqualTo(content.length);
+ }
+
+ @Test
+ public void testBulkReadCountsBytesOnce() throws IOException {
+ byte[] content = "hello".getBytes();
+ FileSystem.Statistics stats = new FileSystem.Statistics("pvfs");
+ VFSInputStream stream = new VFSInputStream(new
ByteArraySeekableStream(content), stats);
+
+ byte[] buffer = new byte[content.length];
+ int byteRead = stream.read(buffer, 0, content.length);
+ stream.close();
+
+ assertThat(byteRead).isEqualTo(content.length);
+ assertThat(buffer).isEqualTo(content);
+ assertThat(stats.getBytesRead()).isEqualTo(content.length);
+ }
+
+ @Test
+ public void testReadAtEofDoesNotCount() throws IOException {
+ FileSystem.Statistics stats = new FileSystem.Statistics("pvfs");
+ VFSInputStream stream =
+ new VFSInputStream(new ByteArraySeekableStream("".getBytes()),
stats);
+
+ assertThat(stream.read()).isEqualTo(-1);
+ stream.close();
+
+ assertThat(stats.getBytesRead()).isEqualTo(0L);
+ }
+}