Skip to content

Commit de66d6b

Browse files
authored
MostFragmentedIntervalFirstPolicy: Implement equals. (#18820)
* MostFragmentedIntervalFirstPolicy: Implement equals. Also hashCode and toString. This is required for correct behavior, since the policy will not be saved to the database on edit if it compares equal to the existing, and the base class BaseCandidateSearchPolicy does have an equals method. So, subclasses such as this one must override equals and hashCode. * Remove unused import.
1 parent c259da5 commit de66d6b

File tree

3 files changed

+80
-1
lines changed

3 files changed

+80
-1
lines changed

server/src/main/java/org/apache/druid/server/compaction/BaseCandidateSearchPolicy.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919

2020
package org.apache.druid.server.compaction;
2121

22+
import com.fasterxml.jackson.annotation.JsonInclude;
2223
import com.fasterxml.jackson.annotation.JsonProperty;
24+
import org.apache.druid.annotations.SubclassesMustOverrideEqualsAndHashCode;
2325
import org.apache.druid.java.util.common.guava.Comparators;
2426

2527
import javax.annotation.Nullable;
@@ -30,6 +32,7 @@
3032
* Base implementation of {@link CompactionCandidateSearchPolicy} that can have
3133
* a {@code priorityDatasource}.
3234
*/
35+
@SubclassesMustOverrideEqualsAndHashCode
3336
public abstract class BaseCandidateSearchPolicy implements CompactionCandidateSearchPolicy
3437
{
3538
private final String priorityDatasource;
@@ -52,6 +55,7 @@ protected BaseCandidateSearchPolicy(@Nullable String priorityDatasource)
5255
*/
5356
@Nullable
5457
@JsonProperty
58+
@JsonInclude(JsonInclude.Include.NON_NULL)
5559
public final String getPriorityDatasource()
5660
{
5761
return priorityDatasource;

server/src/main/java/org/apache/druid/server/compaction/MostFragmentedIntervalFirstPolicy.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import javax.annotation.Nullable;
3030
import java.util.Comparator;
31+
import java.util.Objects;
3132

3233
/**
3334
* Experimental {@link CompactionCandidateSearchPolicy} which prioritizes compaction
@@ -111,6 +112,43 @@ protected Comparator<CompactionCandidate> getSegmentComparator()
111112
return this::compare;
112113
}
113114

115+
@Override
116+
public boolean equals(Object o)
117+
{
118+
if (o == null || getClass() != o.getClass()) {
119+
return false;
120+
}
121+
if (!super.equals(o)) {
122+
return false;
123+
}
124+
MostFragmentedIntervalFirstPolicy policy = (MostFragmentedIntervalFirstPolicy) o;
125+
return minUncompactedCount == policy.minUncompactedCount
126+
&& Objects.equals(minUncompactedBytes, policy.minUncompactedBytes)
127+
&& Objects.equals(maxAverageUncompactedBytesPerSegment, policy.maxAverageUncompactedBytesPerSegment);
128+
}
129+
130+
@Override
131+
public int hashCode()
132+
{
133+
return Objects.hash(
134+
super.hashCode(),
135+
minUncompactedCount,
136+
minUncompactedBytes,
137+
maxAverageUncompactedBytesPerSegment
138+
);
139+
}
140+
141+
@Override
142+
public String toString()
143+
{
144+
return "MostFragmentedIntervalFirstPolicy{" +
145+
"minUncompactedCount=" + minUncompactedCount +
146+
", minUncompactedBytes=" + minUncompactedBytes +
147+
", maxAverageUncompactedBytesPerSegment=" + maxAverageUncompactedBytesPerSegment +
148+
", priorityDataSource='" + getPriorityDatasource() + '\'' +
149+
'}';
150+
}
151+
114152
private int compare(CompactionCandidate candidateA, CompactionCandidate candidateB)
115153
{
116154
final double fragmentationDiff

server/src/test/java/org/apache/druid/server/compaction/MostFragmentedIntervalFirstPolicyTest.java

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@
1919

2020
package org.apache.druid.server.compaction;
2121

22+
import nl.jqno.equalsverifier.EqualsVerifier;
23+
import org.apache.druid.jackson.DefaultObjectMapper;
2224
import org.apache.druid.java.util.common.HumanReadableBytes;
2325
import org.apache.druid.segment.TestDataSource;
2426
import org.apache.druid.server.coordinator.CreateDataSegments;
2527
import org.apache.druid.timeline.DataSegment;
2628
import org.junit.Test;
2729
import org.junit.jupiter.api.Assertions;
2830

31+
import java.io.IOException;
2932
import java.util.List;
3033

3134
public class MostFragmentedIntervalFirstPolicyTest
@@ -192,6 +195,40 @@ public void test_compareCandidates_returnsZeroIfSegmentCountAndAvgSizeScaleEquiv
192195
Assertions.assertEquals(0, policy.compareCandidates(candidateB, candidateA));
193196
}
194197

198+
@Test
199+
public void test_equals()
200+
{
201+
EqualsVerifier.forClass(MostFragmentedIntervalFirstPolicy.class)
202+
.usingGetClass()
203+
.withIgnoredFields("comparator")
204+
.verify();
205+
}
206+
207+
@Test
208+
public void test_serde_allFieldsSet() throws IOException
209+
{
210+
final MostFragmentedIntervalFirstPolicy policy = new MostFragmentedIntervalFirstPolicy(
211+
1,
212+
HumanReadableBytes.valueOf(2),
213+
HumanReadableBytes.valueOf(3),
214+
"foo"
215+
);
216+
final DefaultObjectMapper mapper = new DefaultObjectMapper();
217+
final CompactionCandidateSearchPolicy policy2 =
218+
mapper.readValue(mapper.writeValueAsString(policy), CompactionCandidateSearchPolicy.class);
219+
Assertions.assertEquals(policy, policy2);
220+
}
221+
222+
@Test
223+
public void test_serde_noFieldsSet() throws IOException
224+
{
225+
final MostFragmentedIntervalFirstPolicy policy = new MostFragmentedIntervalFirstPolicy(null, null, null, null);
226+
final DefaultObjectMapper mapper = new DefaultObjectMapper();
227+
final CompactionCandidateSearchPolicy policy2 =
228+
mapper.readValue(mapper.writeValueAsString(policy), CompactionCandidateSearchPolicy.class);
229+
Assertions.assertEquals(policy, policy2);
230+
}
231+
195232
private CompactionCandidate createCandidate(int numSegments, long avgSizeBytes)
196233
{
197234
final CompactionStatistics dummyCompactedStats = CompactionStatistics.create(1L, 1L, 1L);
@@ -201,7 +238,7 @@ private CompactionCandidate createCandidate(int numSegments, long avgSizeBytes)
201238
1L
202239
);
203240
return CompactionCandidate.from(List.of(SEGMENT), null)
204-
.withCurrentStatus(CompactionStatus.pending(dummyCompactedStats, uncompactedStats, ""));
241+
.withCurrentStatus(CompactionStatus.pending(dummyCompactedStats, uncompactedStats, ""));
205242
}
206243

207244
private void verifyCandidateIsEligible(CompactionCandidate candidate, MostFragmentedIntervalFirstPolicy policy)

0 commit comments

Comments
 (0)