steveloughran commented on code in PR #15470:
URL: https://github.com/apache/iceberg/pull/15470#discussion_r3453864669
##########
spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/actions/RewriteTablePathSparkAction.java:
##########
@@ -682,27 +704,120 @@ private static RewriteResult<DeleteFile>
writeDeleteManifest(
specsById,
sourcePrefix,
targetPrefix,
- stagingLocation);
+ stagingLocation,
+ rewrittenDeleteFileSizes.value());
} catch (IOException e) {
throw new RuntimeIOException(e);
}
}
- private void rewritePositionDeletes(Set<DeleteFile> toRewrite) {
+ /**
+ * Enumerate the distinct position delete files referenced by the delete
manifests being
+ * rewritten. Equality delete files are excluded because they hold no
absolute paths and are not
+ * rewritten.
+ */
+ private Set<DeleteFile> positionDeletesToRewrite(Set<ManifestFile>
metaFiles) {
+ Set<ManifestFile> deleteManifests =
+ metaFiles.stream()
+ .filter(manifest -> manifest.content() == ManifestContent.DELETES)
+ .collect(Collectors.toSet());
+ if (deleteManifests.isEmpty()) {
+ return Collections.emptySet();
+ }
+
+ Encoder<ManifestFile> manifestFileEncoder =
Encoders.javaSerialization(ManifestFile.class);
+ Dataset<ManifestFile> manifestDS =
+ spark().createDataset(Lists.newArrayList(deleteManifests),
manifestFileEncoder);
+ Encoder<DeleteFile> deleteFileEncoder =
Encoders.javaSerialization(DeleteFile.class);
+
+ List<DeleteFile> referencedDeleteFiles =
+ manifestDS
+ .repartition(deleteManifests.size())
+ .flatMap(positionDeletesInManifest(tableBroadcast()),
deleteFileEncoder)
+ .collectAsList();
+
+ // DeleteFile does not override equals(); DeleteFileSet dedupes by path so
a delete file shared
+ // across manifests is rewritten only once.
+ DeleteFileSet distinct = DeleteFileSet.create();
+ distinct.addAll(referencedDeleteFiles);
+ return distinct;
+ }
+
+ private static FlatMapFunction<ManifestFile, DeleteFile>
positionDeletesInManifest(
+ Broadcast<Table> tableArg) {
+ return manifestFile -> {
+ Table table = tableArg.getValue();
+ List<DeleteFile> deleteFiles = Lists.newArrayList();
+ try (ManifestReader<DeleteFile> reader =
+ ManifestFiles.readDeleteManifest(manifestFile, table.io(),
table.specs())) {
+ for (DeleteFile deleteFile : reader) {
+ if (deleteFile.content() == FileContent.POSITION_DELETES) {
+ deleteFiles.add(deleteFile.copy());
+ }
+ }
+ }
+ return deleteFiles.iterator();
+ };
+ }
+
+ /**
+ * Rewrite the given position delete files in parallel, returning a map from
each source delete
+ * file path to the size of its rewritten file.
+ */
+ private Map<String, Long> rewritePositionDeletes(Set<DeleteFile> toRewrite) {
if (toRewrite.isEmpty()) {
- return;
+ return Collections.emptyMap();
}
Encoder<DeleteFile> deleteFileEncoder =
Encoders.javaSerialization(DeleteFile.class);
- Dataset<DeleteFile> deleteFileDs =
+ Dataset<DeleteFile> deleteFileDS =
spark().createDataset(Lists.newArrayList(toRewrite),
deleteFileEncoder);
PositionDeleteReaderWriter posDeleteReaderWriter = new
SparkPositionDeleteReaderWriter();
- deleteFileDs
- .repartition(toRewrite.size())
- .foreach(
- rewritePositionDelete(
- tableBroadcast(), sourcePrefix, targetPrefix, stagingDir,
posDeleteReaderWriter));
+ List<Tuple2<String, Long>> rewrittenSizes =
+ deleteFileDS
+ .repartition(toRewrite.size())
+ .map(
+ rewritePositionDelete(
+ tableBroadcast(),
+ sourcePrefix,
+ targetPrefix,
+ stagingDir,
+ posDeleteReaderWriter),
+ Encoders.tuple(Encoders.STRING(), Encoders.LONG()))
+ .collectAsList();
+
+ Map<String, Long> sizesBySourcePath = Maps.newHashMap();
+ for (Tuple2<String, Long> entry : rewrittenSizes) {
+ sizesBySourcePath.put(entry._1(), entry._2());
+ }
+ return sizesBySourcePath;
+ }
+
+ private static MapFunction<DeleteFile, Tuple2<String, Long>>
rewritePositionDelete(
+ Broadcast<Table> tableArg,
+ String sourcePrefixArg,
+ String targetPrefixArg,
+ String stagingLocationArg,
+ PositionDeleteReaderWriter posDeleteReaderWriter) {
+ return deleteFile -> {
+ FileIO io = tableArg.getValue().io();
+ String newPath =
+ RewriteTablePathUtil.stagingPath(
+ deleteFile.location(), sourcePrefixArg, stagingLocationArg);
+ OutputFile outputFile = io.newOutputFile(newPath);
+ PartitionSpec spec =
tableArg.getValue().specs().get(deleteFile.specId());
+ long rewrittenLength =
+ RewriteTablePathUtil.rewritePositionDeleteFileReturningLength(
+ deleteFile,
+ outputFile,
+ io,
+ spec,
+ sourcePrefixArg,
+ targetPrefixArg,
+ posDeleteReaderWriter);
+ return new Tuple2<>(deleteFile.location(), rewrittenLength);
Review Comment:
This is probably the key correctness issue to deal with
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]