blob: 70086abd772aa2c665b76b02596d110d15bd9c50 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.druid.server.coordinator;
import com.google.common.collect.Lists;
import org.apache.druid.client.ImmutableDruidServer;
import org.apache.druid.client.ImmutableDruidServerTests;
import org.apache.druid.java.util.common.DateTimes;
import org.apache.druid.server.coordination.ServerType;
import org.apache.druid.timeline.DataSegment;
import org.apache.druid.timeline.partition.NoneShardSpec;
import org.easymock.EasyMock;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ReservoirSegmentSamplerTest
{
private ImmutableDruidServer druidServer1;
private ImmutableDruidServer druidServer2;
private ImmutableDruidServer druidServer3;
private ImmutableDruidServer druidServer4;
private ServerHolder holder1;
private ServerHolder holder2;
private ServerHolder holder3;
private ServerHolder holder4;
private DataSegment segment1;
private DataSegment segment2;
private DataSegment segment3;
private DataSegment segment4;
List<DataSegment> segments1;
List<DataSegment> segments2;
List<DataSegment> segments3;
List<DataSegment> segments4;
List<DataSegment> segments;
@Before
public void setUp()
{
druidServer1 = EasyMock.createMock(ImmutableDruidServer.class);
druidServer2 = EasyMock.createMock(ImmutableDruidServer.class);
druidServer3 = EasyMock.createMock(ImmutableDruidServer.class);
druidServer4 = EasyMock.createMock(ImmutableDruidServer.class);
holder1 = EasyMock.createMock(ServerHolder.class);
holder2 = EasyMock.createMock(ServerHolder.class);
holder3 = EasyMock.createMock(ServerHolder.class);
holder4 = EasyMock.createMock(ServerHolder.class);
segment1 = EasyMock.createMock(DataSegment.class);
segment2 = EasyMock.createMock(DataSegment.class);
segment3 = EasyMock.createMock(DataSegment.class);
segment4 = EasyMock.createMock(DataSegment.class);
DateTime start1 = DateTimes.of("2012-01-01");
DateTime start2 = DateTimes.of("2012-02-01");
DateTime version = DateTimes.of("2012-03-01");
segment1 = new DataSegment(
"datasource1",
new Interval(start1, start1.plusHours(1)),
version.toString(),
new HashMap<>(),
new ArrayList<>(),
new ArrayList<>(),
NoneShardSpec.instance(),
0,
11L
);
segment2 = new DataSegment(
"datasource1",
new Interval(start2, start2.plusHours(1)),
version.toString(),
new HashMap<>(),
new ArrayList<>(),
new ArrayList<>(),
NoneShardSpec.instance(),
0,
7L
);
segment3 = new DataSegment(
"datasource2",
new Interval(start1, start1.plusHours(1)),
version.toString(),
new HashMap<>(),
new ArrayList<>(),
new ArrayList<>(),
NoneShardSpec.instance(),
0,
4L
);
segment4 = new DataSegment(
"datasource2",
new Interval(start2, start2.plusHours(1)),
version.toString(),
new HashMap<>(),
new ArrayList<>(),
new ArrayList<>(),
NoneShardSpec.instance(),
0,
8L
);
segments = Lists.newArrayList(segment1, segment2, segment3, segment4);
segments1 = Collections.singletonList(segment1);
segments2 = Collections.singletonList(segment2);
segments3 = Collections.singletonList(segment3);
segments4 = Collections.singletonList(segment4);
}
//checks if every segment is selected at least once out of 5000 trials
@Test
public void getRandomBalancerSegmentHolderTest()
{
int iterations = 5000;
EasyMock.expect(druidServer1.getType()).andReturn(ServerType.HISTORICAL).times(iterations);
ImmutableDruidServerTests.expectSegments(druidServer1, segments1);
EasyMock.replay(druidServer1);
EasyMock.expect(druidServer2.getType()).andReturn(ServerType.HISTORICAL).times(iterations);
ImmutableDruidServerTests.expectSegments(druidServer2, segments2);
EasyMock.replay(druidServer2);
EasyMock.expect(druidServer3.getType()).andReturn(ServerType.HISTORICAL).times(iterations);
ImmutableDruidServerTests.expectSegments(druidServer3, segments3);
EasyMock.replay(druidServer3);
EasyMock.expect(druidServer4.getType()).andReturn(ServerType.HISTORICAL).times(iterations);
ImmutableDruidServerTests.expectSegments(druidServer4, segments4);
EasyMock.replay(druidServer4);
// Have to use anyTimes() because the number of times a segment on a given server is chosen is indetermistic.
EasyMock.expect(holder1.getServer()).andReturn(druidServer1).anyTimes();
EasyMock.replay(holder1);
EasyMock.expect(holder2.getServer()).andReturn(druidServer2).anyTimes();
EasyMock.replay(holder2);
EasyMock.expect(holder3.getServer()).andReturn(druidServer3).anyTimes();
EasyMock.replay(holder3);
EasyMock.expect(holder4.getServer()).andReturn(druidServer4).anyTimes();
EasyMock.replay(holder4);
List<ServerHolder> holderList = new ArrayList<>();
holderList.add(holder1);
holderList.add(holder2);
holderList.add(holder3);
holderList.add(holder4);
Map<DataSegment, Integer> segmentCountMap = new HashMap<>();
for (int i = 0; i < iterations; i++) {
// due to the pseudo-randomness of this method, we may not select a segment every single time no matter what.
segmentCountMap.put(
ReservoirSegmentSampler.getRandomBalancerSegmentHolders(holderList, Collections.emptySet(), 1).get(0).getSegment(),
1
);
}
for (DataSegment segment : segments) {
Assert.assertEquals(new Integer(1), segmentCountMap.get(segment));
}
EasyMock.verify(druidServer1, druidServer2, druidServer3, druidServer4);
EasyMock.verify(holder1, holder2, holder3, holder4);
}
/**
* Makes sure that the segment on server4 is never chosen in 5k iterations because it should never have its segment
* checked due to the limit on segment candidates
*/
@Test
public void getRandomBalancerSegmentHolderTestSegmentsToConsiderLimit()
{
int iterations = 5000;
EasyMock.expect(druidServer1.getType()).andReturn(ServerType.HISTORICAL).times(iterations);
ImmutableDruidServerTests.expectSegments(druidServer1, segments1);
EasyMock.replay(druidServer1);
EasyMock.expect(druidServer2.getType()).andReturn(ServerType.HISTORICAL).times(iterations);
ImmutableDruidServerTests.expectSegments(druidServer2, segments2);
EasyMock.replay(druidServer2);
EasyMock.expect(druidServer3.getType()).andReturn(ServerType.HISTORICAL).times(iterations);
ImmutableDruidServerTests.expectSegments(druidServer3, segments3);
EasyMock.replay(druidServer3);
ImmutableDruidServerTests.expectSegments(druidServer4, segments4);
EasyMock.replay(druidServer4);
// Have to use anyTimes() because the number of times a segment on a given server is chosen is indetermistic.
EasyMock.expect(holder1.getServer()).andReturn(druidServer1).anyTimes();
EasyMock.replay(holder1);
EasyMock.expect(holder2.getServer()).andReturn(druidServer2).anyTimes();
EasyMock.replay(holder2);
EasyMock.expect(holder3.getServer()).andReturn(druidServer3).anyTimes();
EasyMock.replay(holder3);
// We only run getServer() each time we calculate the limit on segments to consider. Always 5k
EasyMock.expect(holder4.getServer()).andReturn(druidServer4).times(5000);
EasyMock.replay(holder4);
List<ServerHolder> holderList = new ArrayList<>();
holderList.add(holder1);
holderList.add(holder2);
holderList.add(holder3);
holderList.add(holder4);
Map<DataSegment, Integer> segmentCountMap = new HashMap<>();
for (int i = 0; i < iterations; i++) {
segmentCountMap.put(
ReservoirSegmentSampler.getRandomBalancerSegmentHolder(holderList, Collections.emptySet(), 75).getSegment(), 1
);
}
for (DataSegment segment : segments) {
if (!segment.equals(segment4)) {
Assert.assertEquals(new Integer(1), segmentCountMap.get(segment));
} else {
Assert.assertNull(segmentCountMap.get(segment));
}
}
EasyMock.verify(druidServer1, druidServer2, druidServer3, druidServer4);
EasyMock.verify(holder1, holder2, holder3, holder4);
}
}