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 b297d9079a [core] Carry the row count and byte size a format table
writer already counted (#9121)
b297d9079a is described below
commit b297d9079ad3d6197c651a367ba0889ce9bbdd25
Author: Dapeng Sun(孙大鹏) <[email protected]>
AuthorDate: Mon Aug 10 13:45:04 2026 +0800
[core] Carry the row count and byte size a format table writer already
counted (#9121)
---
.../paimon/partition/PartitionStatistics.java | 42 ++++++++++++++++++++--
.../paimon/partition/PartitionStatisticsTest.java | 32 +++++++++++++++++
.../paimon/io/FormatTableRollingFileWriter.java | 23 ++++++++----
.../paimon/io/FormatTableSingleFileWriter.java | 18 ++++++++++
.../FormatTableWrittenFile.java} | 40 ++++++++++-----------
.../table/format/FileSystemSplitEnumerator.java | 12 ++++++-
.../paimon/table/format/FormatTableFileWriter.java | 18 ++++++----
.../table/format/FormatTableRecordWriter.java | 10 +++---
.../paimon/table/format/TwoPhaseCommitMessage.java | 30 +++++++++++++++-
.../paimon/table/format/FormatTableWriteTest.java | 38 ++++++++++++++------
10 files changed, 209 insertions(+), 54 deletions(-)
diff --git
a/paimon-api/src/main/java/org/apache/paimon/partition/PartitionStatistics.java
b/paimon-api/src/main/java/org/apache/paimon/partition/PartitionStatistics.java
index ab87f02ed6..6717bbc258 100644
---
a/paimon-api/src/main/java/org/apache/paimon/partition/PartitionStatistics.java
+++
b/paimon-api/src/main/java/org/apache/paimon/partition/PartitionStatistics.java
@@ -30,8 +30,23 @@ import java.util.Map;
import java.util.Objects;
/**
- * Statistics of a partition, fields inside may be negative, indicating that
some data has been
- * removed.
+ * Statistics of a partition.
+ *
+ * <p>The numeric fields are read on two planes, and a negative value means a
different thing on
+ * each. Which plane an instance belongs to follows from where it came from,
never from the value:
+ *
+ * <ul>
+ * <li><b>Delta plane</b> — what a commit changed. A negative value is a
decrement, and the server
+ * adds it to what it already holds. This is what a table snapshot
commit reports.
+ * <li><b>Observation plane</b> — what a partition currently holds, as
returned by {@code
+ * listPartitions}. A negative value ({@link #UNKNOWN}) means nobody
ever reported that field,
+ * and {@code 0} means an exact zero. The two are not interchangeable: a
consumer that treats
+ * unknown as zero plans against an empty partition that may hold a
billion rows.
+ * </ul>
+ *
+ * <p>Unknown is per field, not per partition: a reporter that only knows the
file count leaves the
+ * record count {@link #UNKNOWN} and fills the rest. Use {@link
#isKnown(long)} rather than
+ * comparing against {@code -1}; any negative value on the observation plane
is unknown.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
@Public
@@ -39,6 +54,15 @@ public class PartitionStatistics implements Serializable {
private static final long serialVersionUID = 1L;
+ /**
+ * Canonical encoding of "this field was never reported" on the
observation plane. Any negative
+ * value carries the same meaning; this is the one to write.
+ */
+ public static final long UNKNOWN = -1L;
+
+ /** Format tables have no buckets, so their bucket count is always
unknown. */
+ public static final int UNKNOWN_TOTAL_BUCKETS = -1;
+
public static final String FIELD_SPEC = "spec";
public static final String FIELD_RECORD_COUNT = "recordCount";
public static final String FIELD_FILE_SIZE_IN_BYTES = "fileSizeInBytes";
@@ -82,6 +106,20 @@ public class PartitionStatistics implements Serializable {
this.totalBuckets = totalBuckets;
}
+ /** Statistics of a partition nobody ever reported on: every field {@link
#UNKNOWN}. */
+ public static PartitionStatistics unknown(Map<String, String> spec) {
+ return new PartitionStatistics(
+ spec, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN,
UNKNOWN_TOTAL_BUCKETS);
+ }
+
+ /**
+ * Whether an observation-plane field carries a real measurement. Never
apply this to a
+ * delta-plane value, where a negative number is a decrement rather than a
missing measurement.
+ */
+ public static boolean isKnown(long value) {
+ return value >= 0;
+ }
+
@JsonGetter(FIELD_SPEC)
public Map<String, String> spec() {
return spec;
diff --git
a/paimon-api/src/test/java/org/apache/paimon/partition/PartitionStatisticsTest.java
b/paimon-api/src/test/java/org/apache/paimon/partition/PartitionStatisticsTest.java
index d9fd8e8bb1..ec7f12e933 100644
---
a/paimon-api/src/test/java/org/apache/paimon/partition/PartitionStatisticsTest.java
+++
b/paimon-api/src/test/java/org/apache/paimon/partition/PartitionStatisticsTest.java
@@ -22,6 +22,9 @@ import org.apache.paimon.utils.JsonSerdeUtil;
import org.junit.jupiter.api.Test;
+import java.util.Collections;
+import java.util.Map;
+
import static org.assertj.core.api.Assertions.assertThat;
/** Test for {@link PartitionStatistics}. */
@@ -41,4 +44,33 @@ public class PartitionStatisticsTest {
assertThat(stats.lastFileCreationTime()).isEqualTo(123456789L);
assertThat(stats.totalBuckets()).isEqualTo(0);
}
+
+ @Test
+ void testZeroIsAKnownMeasurement() {
+ // The boundary the whole observation-plane contract rests on: an
empty partition was
+ // measured, and a consumer that reads its zero as "nobody looked"
plans against the wrong
+ // table.
+ assertThat(PartitionStatistics.isKnown(0L)).isTrue();
+ assertThat(PartitionStatistics.isKnown(1L)).isTrue();
+ assertThat(PartitionStatistics.isKnown(Long.MAX_VALUE)).isTrue();
+
+
assertThat(PartitionStatistics.isKnown(PartitionStatistics.UNKNOWN)).isFalse();
+ // Unknown is any negative value, not only the canonical -1.
+ assertThat(PartitionStatistics.isKnown(-2L)).isFalse();
+ assertThat(PartitionStatistics.isKnown(Long.MIN_VALUE)).isFalse();
+ }
+
+ @Test
+ void testUnknownLeavesEveryFieldUnknown() {
+ Map<String, String> spec = Collections.singletonMap("pt", "1");
+
+ PartitionStatistics stats = PartitionStatistics.unknown(spec);
+
+ assertThat(stats.spec()).isEqualTo(spec);
+ assertThat(PartitionStatistics.isKnown(stats.recordCount())).isFalse();
+
assertThat(PartitionStatistics.isKnown(stats.fileSizeInBytes())).isFalse();
+ assertThat(PartitionStatistics.isKnown(stats.fileCount())).isFalse();
+
assertThat(PartitionStatistics.isKnown(stats.lastFileCreationTime())).isFalse();
+
assertThat(PartitionStatistics.isKnown(stats.totalBuckets())).isFalse();
+ }
}
diff --git
a/paimon-core/src/main/java/org/apache/paimon/io/FormatTableRollingFileWriter.java
b/paimon-core/src/main/java/org/apache/paimon/io/FormatTableRollingFileWriter.java
index 96e297c327..31ed14fbb1 100644
---
a/paimon-core/src/main/java/org/apache/paimon/io/FormatTableRollingFileWriter.java
+++
b/paimon-core/src/main/java/org/apache/paimon/io/FormatTableRollingFileWriter.java
@@ -45,7 +45,7 @@ public class FormatTableRollingFileWriter implements
AutoCloseable {
private final long targetFileSize;
private final long targetFileRowNum;
private final List<FileWriterAbortExecutor> closedWriters;
- private final List<TwoPhaseOutputStream.Committer> committers;
+ private final List<FormatTableWrittenFile> writtenFiles;
private FormatTableSingleFileWriter currentWriter = null;
private long recordCount = 0;
@@ -75,7 +75,7 @@ public class FormatTableRollingFileWriter implements
AutoCloseable {
this.targetFileSize = targetFileSize;
this.targetFileRowNum = targetFileRowNum;
this.closedWriters = new ArrayList<>();
- this.committers = new ArrayList<>();
+ this.writtenFiles = new ArrayList<>();
}
public long targetFileSize() {
@@ -116,7 +116,14 @@ public class FormatTableRollingFileWriter implements
AutoCloseable {
currentWriter.close();
closedWriters.add(currentWriter.abortExecutor());
if (currentWriter.committers() != null) {
- committers.addAll(currentWriter.committers());
+ // Read the counts off the writer that produced this file: once it
is replaced, the
+ // rows it wrote cannot be recovered without reading the file back.
+ long fileRecordCount = currentWriter.recordCount();
+ long fileSizeInBytes = currentWriter.outputBytes();
+ for (TwoPhaseOutputStream.Committer committer :
currentWriter.committers()) {
+ writtenFiles.add(
+ new FormatTableWrittenFile(committer, fileRecordCount,
fileSizeInBytes));
+ }
}
currentWriter = null;
@@ -128,22 +135,24 @@ public class FormatTableRollingFileWriter implements
AutoCloseable {
currentWriter.abort();
currentWriter = null;
}
- for (TwoPhaseOutputStream.Committer committer : committers) {
+ for (FormatTableWrittenFile writtenFile : writtenFiles) {
+ TwoPhaseOutputStream.Committer committer = writtenFile.committer();
try {
committer.discard(fileIO);
} catch (Throwable e) {
LOG.warn("Exception occurs when discarding file {}.",
committer.targetPath(), e);
}
}
- committers.clear();
+ writtenFiles.clear();
for (FileWriterAbortExecutor abortExecutor : closedWriters) {
abortExecutor.abort();
}
closedWriters.clear();
}
- public List<TwoPhaseOutputStream.Committer> committers() {
- return committers;
+ /** The files this writer produced, each with the rows and bytes it holds.
*/
+ public List<FormatTableWrittenFile> writtenFiles() {
+ return writtenFiles;
}
@Override
diff --git
a/paimon-core/src/main/java/org/apache/paimon/io/FormatTableSingleFileWriter.java
b/paimon-core/src/main/java/org/apache/paimon/io/FormatTableSingleFileWriter.java
index 6290d95391..10e93f7989 100644
---
a/paimon-core/src/main/java/org/apache/paimon/io/FormatTableSingleFileWriter.java
+++
b/paimon-core/src/main/java/org/apache/paimon/io/FormatTableSingleFileWriter.java
@@ -50,6 +50,7 @@ public class FormatTableSingleFileWriter {
private TwoPhaseOutputStream.Committer committer;
protected long outputBytes;
+ protected long recordCount;
protected boolean closed;
public FormatTableSingleFileWriter(
@@ -99,6 +100,7 @@ public class FormatTableSingleFileWriter {
try {
writer.addElement(record);
+ recordCount++;
} catch (Throwable e) {
LOG.warn("Exception occurs when writing file {}. Cleaning up.",
path, e);
abort();
@@ -140,6 +142,22 @@ public class FormatTableSingleFileWriter {
return Lists.newArrayList(committer);
}
+ /** Rows written to this file. Exact, counted as they were written. */
+ public long recordCount() {
+ if (!closed) {
+ throw new RuntimeException("Writer should be closed before getting
record count!");
+ }
+ return recordCount;
+ }
+
+ /** Bytes this file holds, taken from the stream position at close. */
+ public long outputBytes() {
+ if (!closed) {
+ throw new RuntimeException("Writer should be closed before getting
output bytes!");
+ }
+ return outputBytes;
+ }
+
public FileWriterAbortExecutor abortExecutor() {
if (!closed) {
throw new RuntimeException("Writer should be closed!");
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/format/TwoPhaseCommitMessage.java
b/paimon-core/src/main/java/org/apache/paimon/io/FormatTableWrittenFile.java
similarity index 54%
copy from
paimon-core/src/main/java/org/apache/paimon/table/format/TwoPhaseCommitMessage.java
copy to
paimon-core/src/main/java/org/apache/paimon/io/FormatTableWrittenFile.java
index ffb08064dd..f40da268e1 100644
---
a/paimon-core/src/main/java/org/apache/paimon/table/format/TwoPhaseCommitMessage.java
+++ b/paimon-core/src/main/java/org/apache/paimon/io/FormatTableWrittenFile.java
@@ -16,39 +16,37 @@
* limitations under the License.
*/
-package org.apache.paimon.table.format;
+package org.apache.paimon.io;
-import org.apache.paimon.data.BinaryRow;
import org.apache.paimon.fs.TwoPhaseOutputStream;
-import org.apache.paimon.table.sink.CommitMessage;
-import javax.annotation.Nullable;
-
-/** {@link CommitMessage} implementation for format table. */
-public class TwoPhaseCommitMessage implements CommitMessage {
+/**
+ * One data file a format table writer finished, with what it holds. The row
count and byte size are
+ * counted while writing, so carrying them alongside the committer costs no
extra IO and is the only
+ * place they can still be had exactly — after the commit the file is just
bytes on a path.
+ */
+public class FormatTableWrittenFile {
private final TwoPhaseOutputStream.Committer committer;
+ private final long recordCount;
+ private final long fileSizeInBytes;
- public TwoPhaseCommitMessage(TwoPhaseOutputStream.Committer committer) {
+ public FormatTableWrittenFile(
+ TwoPhaseOutputStream.Committer committer, long recordCount, long
fileSizeInBytes) {
this.committer = committer;
+ this.recordCount = recordCount;
+ this.fileSizeInBytes = fileSizeInBytes;
}
- @Override
- public BinaryRow partition() {
- return null;
- }
-
- @Override
- public int bucket() {
- return 0;
+ public TwoPhaseOutputStream.Committer committer() {
+ return committer;
}
- @Override
- public @Nullable Integer totalBuckets() {
- return 0;
+ public long recordCount() {
+ return recordCount;
}
- public TwoPhaseOutputStream.Committer getCommitter() {
- return committer;
+ public long fileSizeInBytes() {
+ return fileSizeInBytes;
}
}
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/format/FileSystemSplitEnumerator.java
b/paimon-core/src/main/java/org/apache/paimon/table/format/FileSystemSplitEnumerator.java
index 7373e35d4d..7d4bccfd15 100644
---
a/paimon-core/src/main/java/org/apache/paimon/table/format/FileSystemSplitEnumerator.java
+++
b/paimon-core/src/main/java/org/apache/paimon/table/format/FileSystemSplitEnumerator.java
@@ -25,6 +25,7 @@ import org.apache.paimon.fs.Path;
import org.apache.paimon.manifest.PartitionEntry;
import org.apache.paimon.partition.PartitionPredicate;
import
org.apache.paimon.partition.PartitionPredicate.MultiplePartitionPredicate;
+import org.apache.paimon.partition.PartitionStatistics;
import org.apache.paimon.predicate.Predicate;
import org.apache.paimon.table.FormatTable;
import org.apache.paimon.table.source.Split;
@@ -125,7 +126,16 @@ final class FileSystemSplitEnumerator extends
SplitEnumerator {
List<PartitionEntry> partitionEntries = new ArrayList<>();
for (Pair<LinkedHashMap<String, String>, Path> partition2Path :
partition2Paths) {
BinaryRow row = toPartitionRow(partition2Path.getKey());
- partitionEntries.add(new PartitionEntry(row, -1L, -1L, -1L, -1L,
-1));
+ // Discovering partitions from directories measures nothing about
what is inside them,
+ // so every statistic is unknown rather than zero.
+ partitionEntries.add(
+ new PartitionEntry(
+ row,
+ PartitionStatistics.UNKNOWN,
+ PartitionStatistics.UNKNOWN,
+ PartitionStatistics.UNKNOWN,
+ PartitionStatistics.UNKNOWN,
+ PartitionStatistics.UNKNOWN_TOTAL_BUCKETS));
}
return partitionEntries;
}
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/format/FormatTableFileWriter.java
b/paimon-core/src/main/java/org/apache/paimon/table/format/FormatTableFileWriter.java
index 9f18ee5758..a3b48ee7fa 100644
---
a/paimon-core/src/main/java/org/apache/paimon/table/format/FormatTableFileWriter.java
+++
b/paimon-core/src/main/java/org/apache/paimon/table/format/FormatTableFileWriter.java
@@ -24,7 +24,7 @@ import org.apache.paimon.data.InternalRow;
import org.apache.paimon.format.FileFormat;
import org.apache.paimon.fs.FileIO;
import org.apache.paimon.fs.Path;
-import org.apache.paimon.fs.TwoPhaseOutputStream;
+import org.apache.paimon.io.FormatTableWrittenFile;
import org.apache.paimon.table.sink.CommitMessage;
import org.apache.paimon.types.RowType;
import org.apache.paimon.utils.FileStorePathFactory;
@@ -97,15 +97,15 @@ public class FormatTableFileWriter {
}
public List<CommitMessage> prepareCommit() throws Exception {
- List<TwoPhaseOutputStream.Committer> committers = new ArrayList<>();
+ List<FormatTableWrittenFile> writtenFiles = new ArrayList<>();
try {
for (FormatTableRecordWriter writer : writers.values()) {
- committers.addAll(writer.closeAndGetCommitters());
+ writtenFiles.addAll(writer.closeAndGetWrittenFiles());
}
} catch (Exception e) {
- for (TwoPhaseOutputStream.Committer committer : committers) {
+ for (FormatTableWrittenFile writtenFile : writtenFiles) {
try {
- committer.discard(fileIO);
+ writtenFile.committer().discard(fileIO);
} catch (Exception cleanupException) {
e.addSuppressed(cleanupException);
}
@@ -119,8 +119,12 @@ public class FormatTableFileWriter {
}
List<CommitMessage> commitMessages = new ArrayList<>();
- for (TwoPhaseOutputStream.Committer committer : committers) {
- commitMessages.add(new TwoPhaseCommitMessage(committer));
+ for (FormatTableWrittenFile writtenFile : writtenFiles) {
+ commitMessages.add(
+ new TwoPhaseCommitMessage(
+ writtenFile.committer(),
+ writtenFile.recordCount(),
+ writtenFile.fileSizeInBytes()));
}
return commitMessages;
}
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/format/FormatTableRecordWriter.java
b/paimon-core/src/main/java/org/apache/paimon/table/format/FormatTableRecordWriter.java
index 83677d9448..3e54f27df9 100644
---
a/paimon-core/src/main/java/org/apache/paimon/table/format/FormatTableRecordWriter.java
+++
b/paimon-core/src/main/java/org/apache/paimon/table/format/FormatTableRecordWriter.java
@@ -21,9 +21,9 @@ package org.apache.paimon.table.format;
import org.apache.paimon.data.InternalRow;
import org.apache.paimon.format.FileFormat;
import org.apache.paimon.fs.FileIO;
-import org.apache.paimon.fs.TwoPhaseOutputStream;
import org.apache.paimon.io.DataFilePathFactory;
import org.apache.paimon.io.FormatTableRollingFileWriter;
+import org.apache.paimon.io.FormatTableWrittenFile;
import org.apache.paimon.types.RowType;
import java.util.ArrayList;
@@ -65,14 +65,14 @@ public class FormatTableRecordWriter implements
AutoCloseable {
writer.write(data);
}
- public List<TwoPhaseOutputStream.Committer> closeAndGetCommitters() throws
Exception {
- List<TwoPhaseOutputStream.Committer> commits = new ArrayList<>();
+ public List<FormatTableWrittenFile> closeAndGetWrittenFiles() throws
Exception {
+ List<FormatTableWrittenFile> written = new ArrayList<>();
if (writer != null) {
writer.close();
- commits.addAll(writer.committers());
+ written.addAll(writer.writtenFiles());
writer = null;
}
- return commits;
+ return written;
}
@Override
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/format/TwoPhaseCommitMessage.java
b/paimon-core/src/main/java/org/apache/paimon/table/format/TwoPhaseCommitMessage.java
index ffb08064dd..f44c5e9b89 100644
---
a/paimon-core/src/main/java/org/apache/paimon/table/format/TwoPhaseCommitMessage.java
+++
b/paimon-core/src/main/java/org/apache/paimon/table/format/TwoPhaseCommitMessage.java
@@ -20,17 +20,35 @@ package org.apache.paimon.table.format;
import org.apache.paimon.data.BinaryRow;
import org.apache.paimon.fs.TwoPhaseOutputStream;
+import org.apache.paimon.partition.PartitionStatistics;
import org.apache.paimon.table.sink.CommitMessage;
import javax.annotation.Nullable;
-/** {@link CommitMessage} implementation for format table. */
+/**
+ * {@link CommitMessage} implementation for format table.
+ *
+ * <p>Carries the row count and byte size of the one file it commits, counted
while writing. The
+ * partition is not carried: {@link FormatTableCommit} derives it from the
committer's target path,
+ * and deriving it once keeps the statistics and the registered partition from
ever disagreeing.
+ */
public class TwoPhaseCommitMessage implements CommitMessage {
+ private static final long serialVersionUID = 1L;
+
private final TwoPhaseOutputStream.Committer committer;
+ private final long recordCount;
+ private final long fileSizeInBytes;
public TwoPhaseCommitMessage(TwoPhaseOutputStream.Committer committer) {
+ this(committer, PartitionStatistics.UNKNOWN,
PartitionStatistics.UNKNOWN);
+ }
+
+ public TwoPhaseCommitMessage(
+ TwoPhaseOutputStream.Committer committer, long recordCount, long
fileSizeInBytes) {
this.committer = committer;
+ this.recordCount = recordCount;
+ this.fileSizeInBytes = fileSizeInBytes;
}
@Override
@@ -51,4 +69,14 @@ public class TwoPhaseCommitMessage implements CommitMessage {
public TwoPhaseOutputStream.Committer getCommitter() {
return committer;
}
+
+ /** Rows in this file, or {@link PartitionStatistics#UNKNOWN} when nobody
counted them. */
+ public long recordCount() {
+ return recordCount;
+ }
+
+ /** Bytes in this file, or {@link PartitionStatistics#UNKNOWN} when nobody
measured them. */
+ public long fileSizeInBytes() {
+ return fileSizeInBytes;
+ }
}
diff --git
a/paimon-core/src/test/java/org/apache/paimon/table/format/FormatTableWriteTest.java
b/paimon-core/src/test/java/org/apache/paimon/table/format/FormatTableWriteTest.java
index 3864f39ad6..4ca81e6a0b 100644
---
a/paimon-core/src/test/java/org/apache/paimon/table/format/FormatTableWriteTest.java
+++
b/paimon-core/src/test/java/org/apache/paimon/table/format/FormatTableWriteTest.java
@@ -41,8 +41,10 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -80,18 +82,32 @@ class FormatTableWriteTest {
}
assertThat(messages).hasSize(3);
- List<Path> dataFiles =
- messages.stream()
- .map(
- message ->
- ((TwoPhaseCommitMessage) message)
- .getCommitter()
- .targetPath())
- .collect(Collectors.toList());
+ // The rows and bytes of each rolled file are counted while writing
and survive to commit,
+ // so they never have to be recovered by reading the file back.
+ assertThat(
+ messages.stream()
+ .map(message -> ((TwoPhaseCommitMessage)
message).recordCount())
+ .collect(Collectors.toList()))
+ .containsExactlyInAnyOrder(2L, 2L, 1L);
+ // Each message carries the size of the one file it commits, not of
some other file that
+ // happens to be positive too.
+ Map<Path, Long> reportedSizes = new LinkedHashMap<>();
+ for (CommitMessage message : messages) {
+ TwoPhaseCommitMessage twoPhase = (TwoPhaseCommitMessage) message;
+ reportedSizes.put(twoPhase.getCommitter().targetPath(),
twoPhase.fileSizeInBytes());
+ }
+ assertThat(reportedSizes).hasSize(messages.size());
+ List<Path> dataFiles = new ArrayList<>(reportedSizes.keySet());
try (BatchTableCommit commit = writeBuilder.newCommit()) {
commit.commit(messages);
}
+ for (Map.Entry<Path, Long> reported : reportedSizes.entrySet()) {
+ assertThat(reported.getValue())
+ .as("byte count reported for %s", reported.getKey())
+ .isEqualTo(fileIO.getFileSize(reported.getKey()));
+ }
+
List<Long> rowCounts =
dataFiles.stream()
.map(
@@ -151,11 +167,13 @@ class FormatTableWriteTest {
TwoPhaseOutputStream.Committer committer =
mock(TwoPhaseOutputStream.Committer.class);
java.util.concurrent.atomic.AtomicInteger closeCount =
new java.util.concurrent.atomic.AtomicInteger();
- when(recordWriter.closeAndGetCommitters())
+ when(recordWriter.closeAndGetWrittenFiles())
.thenAnswer(
ignored -> {
if (closeCount.getAndIncrement() == 0) {
- return Collections.singletonList(committer);
+ return Collections.singletonList(
+ new
org.apache.paimon.io.FormatTableWrittenFile(
+ committer, 1L, 1L));
}
throw new IOException("expected close failure");
});