danny0405 commented on code in PR #13603:
URL: https://github.com/apache/hudi/pull/13603#discussion_r2234855395


##########
hudi-client/hudi-client-common/src/main/java/org/apache/hudi/metadata/HoodieBackedTableMetadataWriter.java:
##########
@@ -1689,40 +1804,75 @@ protected Pair<HoodieData<HoodieRecord>, 
List<HoodieFileGroupId>> tagRecordsWith
     try (HoodieTableFileSystemView fsView = 
HoodieTableMetadataUtil.getFileSystemViewForMetadataTable(metadataMetaClient)) {
       List<HoodieFileGroupId> hoodieFileGroupIdList = new ArrayList<>();
       for (Map.Entry<String, HoodieData<HoodieRecord>> entry : 
partitionRecordsMap.entrySet()) {
-        final String partitionName = entry.getKey();
+        final String partitionPath = entry.getKey();
         HoodieData<HoodieRecord> records = entry.getValue();
+        boolean isPartitionedRLI = Objects.equals(partitionPath, 
RECORD_INDEX.getPartitionPath()) && 
dataWriteConfig.isPartitionedRecordIndexEnabled();
         List<FileSlice> fileSlices =
-            
HoodieTableMetadataUtil.getPartitionLatestFileSlices(metadataMetaClient, 
Option.ofNullable(fsView), partitionName);
-        if (fileSlices.isEmpty()) {
-          // scheduling or initialising of INDEX only initializes the file 
group and not add commit
-          // so if there are no committed file slices, look for inflight slices
-          ValidationUtils.checkState(isInitializing || 
dataMetaClient.getTableConfig().getMetadataPartitionsInflight().contains(partitionName),
-              String.format("Partition %s should be part of inflight metadata 
partitions here %s", partitionName, 
dataMetaClient.getTableConfig().getMetadataPartitionsInflight()));
-          fileSlices = 
getPartitionLatestFileSlicesIncludingInflight(metadataMetaClient, 
Option.ofNullable(fsView), partitionName);
+            
HoodieTableMetadataUtil.getPartitionLatestFileSlices(metadataMetaClient, 
Option.ofNullable(fsView), partitionPath);
+        // scheduling of INDEX only initializes the file group and not add 
commit
+        // so if there are no committed file slices, look for inflight slices
+        if (isPartitionedRLI || fileSlices.isEmpty()) {
+          // For isPartitionedRLI, new partitions added to the data table will 
cause new filegroups that are not yet commited
+          // therefore, we always need to look for inflight filegroups
+          ValidationUtils.checkState(isInitializing || 
dataMetaClient.getTableConfig().getMetadataPartitionsInflight().contains(partitionPath)
 || isPartitionedRLI,
+              String.format("Partition %s should be part of inflight metadata 
partitions here %s", partitionPath, 
dataMetaClient.getTableConfig().getMetadataPartitionsInflight()));
+          fileSlices = 
getPartitionLatestFileSlicesIncludingInflight(metadataMetaClient, 
Option.ofNullable(fsView), partitionPath);
         }
-        final int fileGroupCount = fileSlices.size();
-        ValidationUtils.checkArgument(fileGroupCount > 0, 
String.format("FileGroup count for MDT partition %s should be > 0", 
partitionName));
-        hoodieFileGroupIdList.addAll(fileSlices.stream().map(fileSlice -> new 
HoodieFileGroupId(partitionName, 
fileSlice.getFileId())).collect(Collectors.toList()));
-
-        List<FileSlice> finalFileSlices = fileSlices;
-        HoodieIndexVersion indexVersion = 
existingIndexVersionOrDefault(partitionName, dataMetaClient);
-
-        // Determine key format once per partition to avoid repeated checks
-        SerializableBiFunction<String, Integer, Integer> mappingFunction = 
MetadataPartitionType.fromPartitionPath(partitionName).getFileGroupMappingFunction(indexVersion);
-        HoodieData<HoodieRecord> rddSinglePartitionRecords = records.map(r -> {
-          FileSlice slice = 
finalFileSlices.get(mappingFunction.apply(r.getRecordKey(), fileGroupCount));
-          r.unseal();
-          r.setCurrentLocation(new 
HoodieRecordLocation(slice.getBaseInstantTime(), slice.getFileId()));
-          r.seal();
-          return r;
-        });
-
-        allPartitionRecords = 
allPartitionRecords.union(rddSinglePartitionRecords);
+        hoodieFileGroupIdList.addAll(fileSlices.stream().map(fileSlice -> new 
HoodieFileGroupId(partitionPath, 
fileSlice.getFileId())).collect(Collectors.toList()));
+        SerializableFunction<HoodieRecord, HoodieRecord> recordTagger = 
getRecordTagger(partitionPath, fileSlices);
+        allPartitionRecords = 
allPartitionRecords.union(records.map(recordTagger));
       }
       return Pair.of(allPartitionRecords, hoodieFileGroupIdList);
     }
   }
 
+  private SerializableFunction<HoodieRecord, HoodieRecord> 
getRecordTagger(String partitionPath, List<FileSlice> fileSlices) {
+    HoodieIndexVersion indexVersion = 
existingIndexVersionOrDefault(partitionPath, dataMetaClient);
+    MetadataPartitionType partitionType = 
MetadataPartitionType.fromPartitionPath(partitionPath);
+    // Determine key format once per partition to avoid repeated checks
+    SerializableBiFunction<String, Integer, Integer> mappingFunction = 
partitionType.getFileGroupMappingFunction(indexVersion);
+    if (partitionType == RECORD_INDEX && 
dataWriteConfig.isPartitionedRecordIndexEnabled()) {
+      return getRecordTaggerPartitionedRLI(fileSlices, mappingFunction);
+    }
+    final int fileGroupCount = fileSlices.size();
+    ValidationUtils.checkArgument(fileGroupCount > 0, String.format("FileGroup 
count for MDT partition %s should be > 0", partitionPath));
+    return r -> {
+      FileSlice slice = fileSlices.get(mappingFunction.apply(r.getRecordKey(), 
fileGroupCount));
+      r.unseal();
+      r.setCurrentLocation(new 
HoodieRecordLocation(slice.getBaseInstantTime(), slice.getFileId()));
+      r.seal();
+      return r;
+    };
+  }
+
+  /**
+   * Add the location for each incoming record in the partitioned record level 
index. Hashing needs to be done within the data table partition and
+   * the number of filegroups can also vary by partition. Therefore, we need 
to lookup and group the filegroups by partition to understand the number
+   * of indexes we can hash into
+   *
+   * @param fileSlices latest fileslices in the mdt rli partition
+   * @return the records with the correct location set
+   */
+  private SerializableFunction<HoodieRecord, HoodieRecord> 
getRecordTaggerPartitionedRLI(List<FileSlice> fileSlices, 
SerializableBiFunction<String, Integer, Integer> mappingFunction) {
+    final Map<String, List<HoodieRecordLocation>> fileSlicesPerHudiPartition = 
new HashMap<>();
+    fileSlices.forEach(s -> 
fileSlicesPerHudiPartition.computeIfAbsent(HoodieTableMetadataUtil.getDataTablePartitionNameFromFileGroupName(s.getFileId()),
 x -> new ArrayList<>())
+        .add(new HoodieRecordLocation(s.getBaseInstantTime(), s.getFileId())));
+    return r -> {
+      String partitionPath;
+      if (r.getData() instanceof EmptyHoodieRecordPayloadWithPartition) {
+        partitionPath = ((EmptyHoodieRecordPayloadWithPartition) 
r.getData()).getPartitionPath();
+      } else {
+        partitionPath = ((HoodieMetadataPayload) 
r.getData()).getRecordGlobalLocation().getPartitionPath();

Review Comment:
   `.getRecordGlobalLocation().getPartitionPath()` is not efficient, we may 
need to add a new API on `HoodieMetadataPayload` to fetch the partition path 
directly from `recordIndexMetadata`.



-- 
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]

Reply via email to