xiangfu0 commented on code in PR #19998:
URL: https://github.com/apache/pinot/pull/19998#discussion_r4396810063


##########
pinot-segment-spi/src/main/java/org/apache/pinot/segment/spi/index/metadata/SegmentMetadataImpl.java:
##########
@@ -483,21 +621,136 @@ public String getEndOffset() {
 
   @Override
   public TreeMap<String, ColumnMetadata> getColumnMetadataMap() {
-    return _columnMetadataMap;
+    if (_mappedStore == null) {
+      return _columnMetadataMap;
+    }
+    // Compatibility API for metadata/admin callers. The serving path uses 
column names and direct lookup instead.
+    TreeMap<String, ColumnMetadata> result = new TreeMap<>();
+    for (String column : getPhysicalColumnNames()) {
+      result.put(column, getColumnMetadataFor(column));
+    }
+    result.putAll(_virtualColumnMetadata);
+    return result;
+  }
+
+  /// Returns the physical column names without materializing a metadata map 
or Schema on mapped segments.
+  public Set<String> getPhysicalColumnNames() {
+    return _mappedStore != null ? _physicalColumnNames : 
_schema.getPhysicalColumnNames();
+  }
+
+  @Override
+  public NavigableSet<String> getAllColumns() {
+    if (_mappedStore == null) {
+      return getSchema().getColumnNames();
+    }
+    NavigableSet<String> columns = _mappedAllColumns;
+    if (columns == null) {
+      NavigableSet<String> allColumns = new 
TreeSet<>(getPhysicalColumnNames());
+      allColumns.addAll(_virtualColumnMetadata.keySet());
+      columns = Collections.unmodifiableNavigableSet(allColumns);
+      _mappedAllColumns = columns;
+    }
+    return columns;
+  }
+
+  /// Indicates whether the immutable segment is reading its metadata from the 
binary mapping.
+  public boolean isMapped() {
+    return _mappedStore != null;
+  }
+
+  /// Returns metadata that remains readable after the mapped segment is 
released. Eager metadata already owns its
+  /// column data; a mapped segment needs an eager copy with its serving-time 
column overlays and ZK timestamps.
+  public SegmentMetadataImpl detachedCopy()

Review Comment:
   This is the right fix for handing mapped metadata to callers that outlive 
the segment's reference window — the detached copy holds no store/buffer 
reference (isMapped()==false) and copies every field the eager path exposes, 
including index sizes, ZK timestamps and virtual columns. 
HelixInstanceDataManager builds it before releaseSegment() while the mapping is 
still open, so it's safe. Good.



##########
pinot-segment-local/src/main/java/org/apache/pinot/segment/local/upsert/BasePartitionUpsertMetadataManager.java:
##########
@@ -107,13 +109,20 @@ public abstract class BasePartitionUpsertMetadataManager 
implements PartitionUps
   // Basically, it's possible that some segments in the table partition are 
not tracked here, as their upsert metadata
   // is not managed by the manager currently.
   protected final Set<IndexSegment> _trackedSegments = 
ConcurrentHashMap.newKeySet();
-  // Track all the immutable segments where changes took place since last 
snapshot was taken.
-  // Note: the set can be updated by multiple Helix task threads and the 
consuming thread concurrently. To not miss
-  // segments updated while a snapshot is being taken, the snapshot flow 
removes the exact segments it has persisted
-  // instead of clearing the set, and it retains only the tracked segments at 
the end of each snapshot round to avoid
-  // keeping stale segment object references around.
+  // Track all the immutable segments where changes took place since last 
snapshot was taken, along with their maximum
+  // comparison values. The value must remain readable if a segment is 
destroyed while the snapshot pass is capping
+  // the TTL watermark. Helix task threads and the consuming thread can update 
the map concurrently, so the snapshot
+  // flow removes only the exact segments it persisted and retains tracked 
segments at the end of each round.
   // Skip mutableSegments as only immutable segments are for taking snapshots.
-  protected final Set<ImmutableSegmentImpl> _updatedSegmentsSinceLastSnapshot 
= ConcurrentHashMap.newKeySet();
+  private final ConcurrentHashMap<ImmutableSegmentImpl, Double> 
_updatedSegmentMaxComparisonValues =
+      new ConcurrentHashMap<>();
+  // Keep the protected Set field for extensions compiled against the previous 
API. Both views share one backing map.
+  protected final Set<ImmutableSegmentImpl> _updatedSegmentsSinceLastSnapshot =

Review Comment:
   Good call restoring this to the original Set<ImmutableSegmentImpl> type — 
the prior head had changed it to a ConcurrentMap, which would have broken 
subclasses compiled against the released API. Backing it with 
keySet(TTL_WATERMARK_NOT_SET) keeps the marker semantics correct (an external 
.add() inserts NOT_SET, which getWatermarkToPersist reads under the lock).



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

Reply via email to