kfaraz commented on code in PR #19532:
URL: https://github.com/apache/druid/pull/19532#discussion_r3579171625
##########
server/src/main/java/org/apache/druid/metadata/SqlSegmentsMetadataQuery.java:
##########
@@ -1093,6 +1093,7 @@ public List<Interval>
retrieveUnusedSegmentIntervals(String dataSource, int limi
return
intervals.stream().filter(Objects::nonNull).collect(Collectors.toList());
}
+
Review Comment:
nit: not required
##########
server/src/main/java/org/apache/druid/server/coordinator/duty/BalanceSegments.java:
##########
@@ -50,25 +51,49 @@ public BalanceSegments(Duration coordinatorPeriod)
@Override
public DruidCoordinatorRuntimeParams run(DruidCoordinatorRuntimeParams
params)
{
+ final Stopwatch totalTime = Stopwatch.createStarted();
+
if (params.getUsedSegmentCount() <= 0) {
+ log.info("BalanceSegments skipped: usedSegmentCount[%,d].",
params.getUsedSegmentCount());
Review Comment:
As already called out in the description, please ensure that all the logs
are removed before merging. Otherwise, coordinator logs will become very noisy.
##########
server/src/main/java/org/apache/druid/server/coordinator/loading/StrategicSegmentAssigner.java:
##########
@@ -64,6 +63,10 @@ public class StrategicSegmentAssigner implements
SegmentActionHandler
private final RoundRobinServerSelector serverSelector;
private final BalancerStrategy strategy;
+ // Fixed for the lifetime of this assigner (a new instance is created each
coordinator run),
+ // so it is computed once here rather than on every
replicateSegment/replicateSegmentPartially call.
Review Comment:
This comment can be omitted since we are already maintaining other similar
fields which are valid for the current run such as `historicalTierAliases` and
`tierToAliasName`.
##########
server/src/main/java/org/apache/druid/server/coordinator/DruidCoordinator.java:
##########
@@ -782,11 +783,32 @@ private class UpdateReplicationStatus implements
CoordinatorDuty
@Override
public DruidCoordinatorRuntimeParams run(DruidCoordinatorRuntimeParams
params)
{
+ final Stopwatch totalTime = Stopwatch.createStarted();
+
+ final Stopwatch broadcastTime = Stopwatch.createStarted();
Review Comment:
Please remove these stopwatches as well before merging this PR.
##########
server/src/main/java/org/apache/druid/server/coordinator/loading/StrategicSegmentAssigner.java:
##########
@@ -86,6 +89,9 @@ public StrategicSegmentAssigner(
this.cluster = cluster;
this.strategy = strategy;
this.loadQueueManager = loadQueueManager;
+ final Set<String> allTiersInCluster = new HashSet<>();
+ cluster.getTierNames().forEach(allTiersInCluster::add);
+ this.allTiersInCluster = allTiersInCluster;
Review Comment:
to ensure immutability:
```suggestion
this.allTiersInCluster = Set.copyOf(cluster.getTierNames());
```
##########
server/src/main/java/org/apache/druid/server/coordinator/duty/MarkOvershadowedSegmentsAsUnused.java:
##########
@@ -80,23 +80,33 @@ public DruidCoordinatorRuntimeParams
run(DruidCoordinatorRuntimeParams params)
return params;
}
+ // Identify the datasources that actually have overshadowed segments to
check.
+ // Timelines only need to be built for these datasources.
+ final Set<String> relevantDatasources = new HashSet<>();
+ for (DataSegment s : allOvershadowedSegments) {
+ relevantDatasources.add(s.getDataSource());
+ }
Review Comment:
Nit: rename and make immutable
```suggestion
final Set<String> eligibleDatasources = allOvershadowedSegments
.stream()
.map(DataSegment::getDataSource)
.collect(Collectors.toSet());
```
##########
server/src/main/java/org/apache/druid/server/coordinator/duty/MarkOvershadowedSegmentsAsUnused.java:
##########
@@ -80,23 +80,33 @@ public DruidCoordinatorRuntimeParams
run(DruidCoordinatorRuntimeParams params)
return params;
}
+ // Identify the datasources that actually have overshadowed segments to
check.
+ // Timelines only need to be built for these datasources.
+ final Set<String> relevantDatasources = new HashSet<>();
Review Comment:
```suggestion
final Set<String> eligibleDatasources = new HashSet<>();
```
##########
server/src/main/java/org/apache/druid/server/coordinator/duty/MarkEternityTombstonesAsUnused.java:
##########
@@ -132,43 +130,57 @@ public DruidCoordinatorRuntimeParams run(final
DruidCoordinatorRuntimeParams par
private Map<String, Set<SegmentId>>
determineNonOvershadowedEternityTombstones(final DataSourcesSnapshot
dataSourcesSnapshot)
{
final Map<String, Set<SegmentId>>
datasourceToNonOvershadowedEternityTombstones = new HashMap<>();
+ final Map<String, Set<DataSegment>> overshadowedSegmentsByDatasource = new
HashMap<>();
- dataSourcesSnapshot.getDataSourcesMap().keySet().forEach((datasource) -> {
+ for (final DataSegment overshadowedSegment :
dataSourcesSnapshot.getOvershadowedSegments()) {
+ overshadowedSegmentsByDatasource
+ .computeIfAbsent(overshadowedSegment.getDataSource(), ds -> new
HashSet<>())
+ .add(overshadowedSegment);
+ }
+
+ for (final ImmutableDruidDataSource dataSource :
dataSourcesSnapshot.getDataSourcesWithAllUsedSegments()) {
+ final String datasource = dataSource.getName();
Review Comment:
To avoid confusion with the other variable `dataSource`.
```suggestion
final String datasourceName = dataSource.getName();
```
##########
server/src/main/java/org/apache/druid/server/coordinator/loading/SegmentReplicaCount.java:
##########
@@ -36,6 +36,25 @@ public class SegmentReplicaCount
private int movingTo;
private int movingFrom;
+ SegmentReplicaCount()
+ {
+ }
+
+ /**
+ * Copies the counts out of {@code other} into a new, independent instance.
+ */
+ SegmentReplicaCount(SegmentReplicaCount other)
Review Comment:
Instead of this, maybe add a `copy()` method.
##########
server/src/main/java/org/apache/druid/server/coordinator/loading/SegmentReplicaCount.java:
##########
@@ -36,6 +36,25 @@ public class SegmentReplicaCount
private int movingTo;
private int movingFrom;
+ SegmentReplicaCount()
Review Comment:
This shouldn't be needed.
##########
server/src/main/java/org/apache/druid/server/coordinator/duty/PrepareBalancerAndLoadQueues.java:
##########
@@ -203,14 +203,14 @@ private void collectHistoricalStats(
private void collectUsedSegmentStats(DruidCoordinatorRuntimeParams params,
CoordinatorRunStats stats)
{
- params.getUsedSegmentsTimelinesPerDataSource().forEach((dataSource,
timeline) -> {
- long totalSizeOfUsedSegments = timeline.iterateAllObjects().stream()
-
.mapToLong(DataSegment::getSize).sum();
+ for (final ImmutableDruidDataSource dataSource :
params.getDataSourcesSnapshot().getDataSourcesWithAllUsedSegments()) {
+ final long totalSizeOfUsedSegments = dataSource.getTotalSizeOfSegments();
+ final int numUsedSegments = dataSource.getSegments().size();
Review Comment:
We should also add a method `DataSourcesSnapshot.getNumSegments()` to avoid
materializing the collection inside `DataSourcesSnapshot.getSegments()`.
##########
server/src/main/java/org/apache/druid/server/coordinator/DruidCoordinator.java:
##########
@@ -801,26 +803,46 @@ public DruidCoordinatorRuntimeParams
run(DruidCoordinatorRuntimeParams params)
{
// Collect stats for unavailable and under-replicated segments
final CoordinatorRunStats stats = params.getCoordinatorStats();
- getDatasourceToUnavailableSegmentCount().forEach(
- (dataSource, numUnavailable) -> stats.add(
- Stats.Segments.UNAVAILABLE,
- RowKey.of(Dimension.DATASOURCE, dataSource),
- numUnavailable
- )
- );
- getTierToDatasourceToUnderReplicatedCount(false).forEach(
- (tier, countsPerDatasource) -> countsPerDatasource.forEach(
- (dataSource, underReplicatedCount) ->
- stats.addToSegmentStat(Stats.Segments.UNDER_REPLICATED,
tier, dataSource, underReplicatedCount)
- )
- );
- getDatasourceToDeepStorageQueryOnlySegmentCount().forEach(
- (dataSource, numDeepStorageOnly) -> stats.add(
- Stats.Segments.DEEP_STORAGE_ONLY,
- RowKey.of(Dimension.DATASOURCE, dataSource),
- numDeepStorageOnly
- )
- );
+
+ final Object2IntMap<String> dsToUnavailable;
+ final Map<String, Object2LongMap<String>> tierToDsToUnderRepl;
+ final Object2IntMap<String> dsToDeepStorageOnly;
+
+ if (segmentReplicationStatus == null) {
+ dsToUnavailable = Object2IntMaps.emptyMap();
+ tierToDsToUnderRepl = Collections.emptyMap();
+ dsToDeepStorageOnly = Object2IntMaps.emptyMap();
+ } else {
+ // Single fused pass replaces three independent full iterations over
+ // metadataManager.iterateAllUsedSegments(). ignoreMissingServers=true
replicates
+ // the !false inversion inside computeUnderReplicated(segments, false).
+ final SegmentReplicationStatus.SegmentStatsSnapshot snapshot =
segmentReplicationStatus.computeSegmentStats(
+ metadataManager.iterateAllUsedSegments(),
+ true
+ );
+ dsToUnavailable = snapshot.getDatasourceToUnavailableCount();
+ tierToDsToUnderRepl =
snapshot.getTierToDatasourceToUnderReplicatedCount();
+ dsToDeepStorageOnly = snapshot.getDatasourceToDeepStorageOnlyCount();
+ }
+
+ for (final Object2IntMap.Entry<String> e :
dsToUnavailable.object2IntEntrySet()) {
+ stats.add(Stats.Segments.UNAVAILABLE, RowKey.of(Dimension.DATASOURCE,
e.getKey()), e.getIntValue());
+ }
+
+ for (final Map.Entry<String, Object2LongMap<String>> tierEntry :
tierToDsToUnderRepl.entrySet()) {
Review Comment:
Using `forEach` and `fastForEach` instead of traditional for loops may make
this more readable.
##########
server/src/main/java/org/apache/druid/server/coordinator/duty/MarkEternityTombstonesAsUnused.java:
##########
@@ -132,43 +130,57 @@ public DruidCoordinatorRuntimeParams run(final
DruidCoordinatorRuntimeParams par
private Map<String, Set<SegmentId>>
determineNonOvershadowedEternityTombstones(final DataSourcesSnapshot
dataSourcesSnapshot)
{
final Map<String, Set<SegmentId>>
datasourceToNonOvershadowedEternityTombstones = new HashMap<>();
+ final Map<String, Set<DataSegment>> overshadowedSegmentsByDatasource = new
HashMap<>();
- dataSourcesSnapshot.getDataSourcesMap().keySet().forEach((datasource) -> {
+ for (final DataSegment overshadowedSegment :
dataSourcesSnapshot.getOvershadowedSegments()) {
+ overshadowedSegmentsByDatasource
+ .computeIfAbsent(overshadowedSegment.getDataSource(), ds -> new
HashSet<>())
+ .add(overshadowedSegment);
+ }
+
+ for (final ImmutableDruidDataSource dataSource :
dataSourcesSnapshot.getDataSourcesWithAllUsedSegments()) {
+ final String datasource = dataSource.getName();
final SegmentTimeline usedSegmentsTimeline
=
dataSourcesSnapshot.getUsedSegmentsTimelinesPerDataSource().get(datasource);
+ if (usedSegmentsTimeline == null) {
Review Comment:
Can this ever happen? We are already iterating over the datasources provided
by the snapshot itself.
##########
server/src/main/java/org/apache/druid/server/coordinator/duty/MarkEternityTombstonesAsUnused.java:
##########
@@ -132,43 +130,57 @@ public DruidCoordinatorRuntimeParams run(final
DruidCoordinatorRuntimeParams par
private Map<String, Set<SegmentId>>
determineNonOvershadowedEternityTombstones(final DataSourcesSnapshot
dataSourcesSnapshot)
{
final Map<String, Set<SegmentId>>
datasourceToNonOvershadowedEternityTombstones = new HashMap<>();
+ final Map<String, Set<DataSegment>> overshadowedSegmentsByDatasource = new
HashMap<>();
- dataSourcesSnapshot.getDataSourcesMap().keySet().forEach((datasource) -> {
+ for (final DataSegment overshadowedSegment :
dataSourcesSnapshot.getOvershadowedSegments()) {
+ overshadowedSegmentsByDatasource
+ .computeIfAbsent(overshadowedSegment.getDataSource(), ds -> new
HashSet<>())
+ .add(overshadowedSegment);
+ }
+
+ for (final ImmutableDruidDataSource dataSource :
dataSourcesSnapshot.getDataSourcesWithAllUsedSegments()) {
+ final String datasource = dataSource.getName();
final SegmentTimeline usedSegmentsTimeline
=
dataSourcesSnapshot.getUsedSegmentsTimelinesPerDataSource().get(datasource);
+ if (usedSegmentsTimeline == null) {
+ continue;
+ }
- final Optional<Set<DataSegment>> usedNonOvershadowedSegments =
- Optional.fromNullable(usedSegmentsTimeline)
- .transform(timeline ->
timeline.findNonOvershadowedObjectsInInterval(
- Intervals.ETERNITY,
- Partitions.ONLY_COMPLETE
- ));
-
- if (usedNonOvershadowedSegments.isPresent()) {
- usedNonOvershadowedSegments.get().forEach(candidateSegment -> {
- if (isNewGenerationEternityTombstone(candidateSegment)) {
- boolean overlaps =
dataSourcesSnapshot.getOvershadowedSegments().stream()
- .filter(overshadowedSegment
->
-
candidateSegment.getDataSource()
-
.equals(overshadowedSegment.getDataSource()))
- .anyMatch(
- overshadowedSegment ->
-
candidateSegment.getInterval()
-
.overlaps(overshadowedSegment.getInterval())
- );
- if (!overlaps) {
- datasourceToNonOvershadowedEternityTombstones
- .computeIfAbsent(datasource, ds -> new HashSet<>())
- .add(candidateSegment.getId());
- }
- }
- });
+ for (final DataSegment candidateSegment : dataSource.getSegments()) {
+ if (isNewGenerationEternityTombstone(candidateSegment)
+ && !usedSegmentsTimeline.isOvershadowed(candidateSegment)
+ && !overlapsAnyOvershadowedSegment(
+ candidateSegment,
+
overshadowedSegmentsByDatasource.get(candidateSegment.getDataSource())
+ )) {
Review Comment:
Let's collapse these 3 conditions into a single new method for readability
of this for loop:
```
shouldMarkAsUnused(candidateSegment, overshadowedSegmentsByDatasource,
timeline)
```
the new method can check the 3 required conditions by invoking respective
methods.
##########
server/src/main/java/org/apache/druid/server/coordinator/DruidCoordinator.java:
##########
@@ -801,26 +803,46 @@ public DruidCoordinatorRuntimeParams
run(DruidCoordinatorRuntimeParams params)
{
// Collect stats for unavailable and under-replicated segments
final CoordinatorRunStats stats = params.getCoordinatorStats();
- getDatasourceToUnavailableSegmentCount().forEach(
- (dataSource, numUnavailable) -> stats.add(
- Stats.Segments.UNAVAILABLE,
- RowKey.of(Dimension.DATASOURCE, dataSource),
- numUnavailable
- )
- );
- getTierToDatasourceToUnderReplicatedCount(false).forEach(
- (tier, countsPerDatasource) -> countsPerDatasource.forEach(
- (dataSource, underReplicatedCount) ->
- stats.addToSegmentStat(Stats.Segments.UNDER_REPLICATED,
tier, dataSource, underReplicatedCount)
- )
- );
- getDatasourceToDeepStorageQueryOnlySegmentCount().forEach(
- (dataSource, numDeepStorageOnly) -> stats.add(
- Stats.Segments.DEEP_STORAGE_ONLY,
- RowKey.of(Dimension.DATASOURCE, dataSource),
- numDeepStorageOnly
- )
- );
+
+ final Object2IntMap<String> dsToUnavailable;
+ final Map<String, Object2LongMap<String>> tierToDsToUnderRepl;
+ final Object2IntMap<String> dsToDeepStorageOnly;
Review Comment:
Please use full names e.g. `datasourceToUnavailableCount`,
`datasourceToUnderReplicatedCount`.
Do we need to keep 3 separate map references? Maybe just use an empty
instance of `SegmentStatsSnapshot` and invoke getters on it where needed.
##########
server/src/main/java/org/apache/druid/server/coordinator/loading/SegmentReplicationStatus.java:
##########
@@ -40,15 +43,27 @@ public class SegmentReplicationStatus
public SegmentReplicationStatus(Map<SegmentId, Map<String,
SegmentReplicaCount>> replicaCountsInTier)
{
- this.replicaCountsInTier = ImmutableMap.copyOf(replicaCountsInTier);
-
- final Map<SegmentId, SegmentReplicaCount> totalReplicaCounts = new
HashMap<>();
- replicaCountsInTier.forEach((segmentId, tierToReplicaCount) -> {
+ // replicaCountsInTier is the caller's live SegmentReplicaCountMap and is
mutated further
+ // in the same coordinator cycle (e.g. by BalanceSegments), so we must
snapshot both the
+ // structure and the per-tier SegmentReplicaCount values, not just alias
the outer map.
Review Comment:
Nit: simpler language
```suggestion
// Make a deep copy of replicaCountsInTier as it may be mutated further
// in the same coordinator cycle (e.g. by BalanceSegments)
```
##########
server/src/main/java/org/apache/druid/server/coordinator/duty/RunRules.java:
##########
@@ -98,14 +99,15 @@ public DruidCoordinatorRuntimeParams
run(DruidCoordinatorRuntimeParams params)
final DateTime now = DateTimes.nowUtc();
final Object2IntOpenHashMap<String> datasourceToSegmentsWithNoRule = new
Object2IntOpenHashMap<>();
+ final Map<String, List<Rule>> datasourceToRules = new HashMap<>();
Review Comment:
Rules need not be cached as they are already served from the cache in
`SQLMetadataRuleManager` itself. The changes to this class may be reverted.
##########
server/src/main/java/org/apache/druid/server/coordinator/loading/SegmentReplicationStatus.java:
##########
@@ -81,4 +96,84 @@ public Map<String, Object2LongMap<String>>
getTierToDatasourceToUnderReplicated(
return tierToUnderReplicated;
}
+
+ /**
+ * Computes unavailable, under-replicated and deep-storage-only segment
counts in a single
+ * pass over {@code usedSegments}, instead of three independent full
iterations. Produces
+ * results identical to calling {@link #getReplicaCountsInCluster} and
+ * {@link #getTierToDatasourceToUnderReplicated} independently for each
segment.
+ *
+ * @param ignoreMissingServers same semantics as in {@link
#getTierToDatasourceToUnderReplicated}.
+ */
+ public SegmentStatsSnapshot computeSegmentStats(Iterable<DataSegment>
usedSegments, boolean ignoreMissingServers)
+ {
+ final Object2IntOpenHashMap<String> datasourceToUnavailable = new
Object2IntOpenHashMap<>();
+ final Object2IntOpenHashMap<String> datasourceToDeepStorageOnly = new
Object2IntOpenHashMap<>();
+ final Map<String, Object2LongMap<String>> tierToUnderReplicated = new
HashMap<>();
+
+ for (DataSegment segment : usedSegments) {
+ final SegmentId segmentId = segment.getId();
+ final String datasource = segment.getDataSource();
+
+ final SegmentReplicaCount totalCount = totalReplicaCounts.get(segmentId);
+ if (totalCount != null && (totalCount.totalLoaded() > 0 ||
totalCount.required() == 0)) {
+ datasourceToUnavailable.addTo(datasource, 0);
+ } else {
+ datasourceToUnavailable.addTo(datasource, 1);
+ }
+ if (totalCount != null && totalCount.totalLoaded() == 0 &&
totalCount.required() == 0) {
+ datasourceToDeepStorageOnly.addTo(datasource, 1);
+ }
+
+ final Map<String, SegmentReplicaCount> tierToReplicaCount =
replicaCountsInTier.get(segmentId);
+ if (tierToReplicaCount != null) {
+ tierToReplicaCount.forEach((tier, counts) -> {
+ final int underReplicated = ignoreMissingServers ? counts.missing()
: counts.missingAndLoadable();
+ if (underReplicated >= 0) {
+ Object2LongOpenHashMap<String> datasourceToUnderReplicated =
(Object2LongOpenHashMap<String>)
+ tierToUnderReplicated.computeIfAbsent(tier, ds -> new
Object2LongOpenHashMap<>());
+ datasourceToUnderReplicated.addTo(datasource, underReplicated);
+ }
+ });
Review Comment:
Can we replace this by a call to `getTierToDatasourceToUnderReplicated()`
since it is the same logic?
##########
server/src/main/java/org/apache/druid/server/coordinator/loading/SegmentReplicationStatus.java:
##########
@@ -81,4 +96,84 @@ public Map<String, Object2LongMap<String>>
getTierToDatasourceToUnderReplicated(
return tierToUnderReplicated;
}
+
+ /**
+ * Computes unavailable, under-replicated and deep-storage-only segment
counts in a single
+ * pass over {@code usedSegments}, instead of three independent full
iterations. Produces
+ * results identical to calling {@link #getReplicaCountsInCluster} and
+ * {@link #getTierToDatasourceToUnderReplicated} independently for each
segment.
+ *
+ * @param ignoreMissingServers same semantics as in {@link
#getTierToDatasourceToUnderReplicated}.
+ */
+ public SegmentStatsSnapshot computeSegmentStats(Iterable<DataSegment>
usedSegments, boolean ignoreMissingServers)
+ {
+ final Object2IntOpenHashMap<String> datasourceToUnavailable = new
Object2IntOpenHashMap<>();
+ final Object2IntOpenHashMap<String> datasourceToDeepStorageOnly = new
Object2IntOpenHashMap<>();
+ final Map<String, Object2LongMap<String>> tierToUnderReplicated = new
HashMap<>();
+
+ for (DataSegment segment : usedSegments) {
+ final SegmentId segmentId = segment.getId();
+ final String datasource = segment.getDataSource();
+
+ final SegmentReplicaCount totalCount = totalReplicaCounts.get(segmentId);
+ if (totalCount != null && (totalCount.totalLoaded() > 0 ||
totalCount.required() == 0)) {
+ datasourceToUnavailable.addTo(datasource, 0);
+ } else {
+ datasourceToUnavailable.addTo(datasource, 1);
+ }
+ if (totalCount != null && totalCount.totalLoaded() == 0 &&
totalCount.required() == 0) {
+ datasourceToDeepStorageOnly.addTo(datasource, 1);
+ }
+
+ final Map<String, SegmentReplicaCount> tierToReplicaCount =
replicaCountsInTier.get(segmentId);
+ if (tierToReplicaCount != null) {
+ tierToReplicaCount.forEach((tier, counts) -> {
+ final int underReplicated = ignoreMissingServers ? counts.missing()
: counts.missingAndLoadable();
+ if (underReplicated >= 0) {
+ Object2LongOpenHashMap<String> datasourceToUnderReplicated =
(Object2LongOpenHashMap<String>)
+ tierToUnderReplicated.computeIfAbsent(tier, ds -> new
Object2LongOpenHashMap<>());
+ datasourceToUnderReplicated.addTo(datasource, underReplicated);
+ }
+ });
+ }
+ }
+
+ return new SegmentStatsSnapshot(datasourceToUnavailable,
tierToUnderReplicated, datasourceToDeepStorageOnly);
+ }
+
+ /**
+ * Holder for the three segment-stat views computed together by {@link
#computeSegmentStats}.
+ */
+ public static class SegmentStatsSnapshot
Review Comment:
Please move out this class into a separate file as it seems completely
independent.
##########
server/src/main/java/org/apache/druid/server/coordinator/loading/SegmentReplicationStatus.java:
##########
@@ -81,4 +96,84 @@ public Map<String, Object2LongMap<String>>
getTierToDatasourceToUnderReplicated(
return tierToUnderReplicated;
}
+
+ /**
+ * Computes unavailable, under-replicated and deep-storage-only segment
counts in a single
+ * pass over {@code usedSegments}, instead of three independent full
iterations. Produces
+ * results identical to calling {@link #getReplicaCountsInCluster} and
+ * {@link #getTierToDatasourceToUnderReplicated} independently for each
segment.
+ *
+ * @param ignoreMissingServers same semantics as in {@link
#getTierToDatasourceToUnderReplicated}.
+ */
+ public SegmentStatsSnapshot computeSegmentStats(Iterable<DataSegment>
usedSegments, boolean ignoreMissingServers)
+ {
+ final Object2IntOpenHashMap<String> datasourceToUnavailable = new
Object2IntOpenHashMap<>();
+ final Object2IntOpenHashMap<String> datasourceToDeepStorageOnly = new
Object2IntOpenHashMap<>();
+ final Map<String, Object2LongMap<String>> tierToUnderReplicated = new
HashMap<>();
+
+ for (DataSegment segment : usedSegments) {
+ final SegmentId segmentId = segment.getId();
+ final String datasource = segment.getDataSource();
+
+ final SegmentReplicaCount totalCount = totalReplicaCounts.get(segmentId);
+ if (totalCount != null && (totalCount.totalLoaded() > 0 ||
totalCount.required() == 0)) {
+ datasourceToUnavailable.addTo(datasource, 0);
+ } else {
+ datasourceToUnavailable.addTo(datasource, 1);
+ }
+ if (totalCount != null && totalCount.totalLoaded() == 0 &&
totalCount.required() == 0) {
+ datasourceToDeepStorageOnly.addTo(datasource, 1);
+ }
Review Comment:
This logic is now duplicated with `DruidCoordinator`.
Please move unavailable logic and deep storage logic into new methods in
this class so that `DruidCoordinator` may reuse it too.
```java
boolean isUnavailable(SegmentId segmentId);
boolean isUnderReplicated(SegmentId segmentId);
```
--
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]