|
20 | 20 | package org.apache.iceberg.arrow.vectorized; |
21 | 21 |
|
22 | 22 | import java.io.IOException; |
| 23 | +import java.nio.ByteBuffer; |
23 | 24 | import java.util.Collection; |
24 | | -import java.util.Collections; |
25 | 25 | import java.util.Iterator; |
26 | 26 | import java.util.List; |
27 | 27 | import java.util.Map; |
28 | | -import java.util.function.Function; |
29 | 28 | import java.util.stream.Collectors; |
30 | 29 | import java.util.stream.Stream; |
31 | 30 | import java.util.stream.StreamSupport; |
|
38 | 37 | import org.apache.iceberg.Schema; |
39 | 38 | import org.apache.iceberg.TableScan; |
40 | 39 | import org.apache.iceberg.encryption.EncryptedFiles; |
| 40 | +import org.apache.iceberg.encryption.EncryptedInputFile; |
41 | 41 | import org.apache.iceberg.encryption.EncryptionManager; |
42 | 42 | import org.apache.iceberg.io.CloseableGroup; |
43 | 43 | import org.apache.iceberg.io.CloseableIterable; |
|
49 | 49 | import org.apache.iceberg.parquet.TypeWithSchemaVisitor; |
50 | 50 | import org.apache.iceberg.relocated.com.google.common.base.Preconditions; |
51 | 51 | import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap; |
| 52 | +import org.apache.iceberg.relocated.com.google.common.collect.Maps; |
52 | 53 | import org.apache.iceberg.types.Types; |
53 | 54 | import org.apache.parquet.schema.MessageType; |
54 | 55 |
|
@@ -210,11 +211,21 @@ private static final class VectorizedCombinedScanIterator implements CloseableIt |
210 | 211 | .flatMap(Collection::stream) |
211 | 212 | .collect(Collectors.toList()); |
212 | 213 | this.fileItr = fileTasks.iterator(); |
213 | | - this.inputFiles = Collections.unmodifiableMap(fileTasks.stream() |
| 214 | + |
| 215 | + Map<String, ByteBuffer> keyMetadata = Maps.newHashMap(); |
| 216 | + fileTasks.stream() |
214 | 217 | .flatMap(fileScanTask -> Stream.concat(Stream.of(fileScanTask.file()), fileScanTask.deletes().stream())) |
215 | | - .map(file -> EncryptedFiles.encryptedInput(io.newInputFile(file.path().toString()), file.keyMetadata())) |
216 | | - .map(encryptionManager::decrypt) |
217 | | - .collect(Collectors.toMap(InputFile::location, Function.identity()))); |
| 218 | + .forEach(file -> keyMetadata.put(file.path().toString(), file.keyMetadata())); |
| 219 | + |
| 220 | + Stream<EncryptedInputFile> encrypted = keyMetadata.entrySet().stream() |
| 221 | + .map(entry -> EncryptedFiles.encryptedInput(io.newInputFile(entry.getKey()), entry.getValue())); |
| 222 | + |
| 223 | + // decrypt with the batch call to avoid multiple RPCs to a key server, if possible |
| 224 | + Iterable<InputFile> decryptedFiles = encryptionManager.decrypt(encrypted::iterator); |
| 225 | + |
| 226 | + Map<String, InputFile> files = Maps.newHashMapWithExpectedSize(fileTasks.size()); |
| 227 | + decryptedFiles.forEach(decrypted -> files.putIfAbsent(decrypted.location(), decrypted)); |
| 228 | + this.inputFiles = ImmutableMap.copyOf(files); |
218 | 229 | this.currentIterator = CloseableIterator.empty(); |
219 | 230 | this.expectedSchema = expectedSchema; |
220 | 231 | this.nameMapping = nameMapping; |
|
0 commit comments