use of com.linkedin.pinot.common.utils.LLCSegmentName in project pinot by linkedin.
the class PinotLLCRealtimeSegmentManagerTest method testCommittingSegment.
@Test
public void testCommittingSegment() throws Exception {
FakePinotLLCRealtimeSegmentManager segmentManager = new FakePinotLLCRealtimeSegmentManager(true, null);
final String topic = "someTopic";
final String rtTableName = "table_REALTIME";
final String rawTableName = TableNameBuilder.extractRawTableName(rtTableName);
final int nInstances = 6;
final int nPartitions = 16;
final int nReplicas = 3;
final boolean existingIS = false;
List<String> instances = getInstanceList(nInstances);
final String startOffset = KAFKA_OFFSET;
IdealState idealState = PinotTableIdealStateBuilder.buildEmptyKafkaConsumerRealtimeIdealStateFor(rtTableName, nReplicas);
segmentManager.setupHelixEntries(topic, rtTableName, nPartitions, instances, nReplicas, startOffset, DUMMY_HOST, idealState, !existingIS, 10000);
// Now commit the first segment of partition 6.
final int committingPartition = 6;
final long nextOffset = 3425666L;
LLCRealtimeSegmentZKMetadata committingSegmentMetadata = new LLCRealtimeSegmentZKMetadata(segmentManager._records.get(committingPartition));
segmentManager._paths.clear();
segmentManager._records.clear();
boolean status = segmentManager.commitSegment(rawTableName, committingSegmentMetadata.getSegmentName(), nextOffset);
segmentManager.verifyMetadataInteractions();
Assert.assertTrue(status);
// Get the old and new segment metadata and make sure that they are correct.
Assert.assertEquals(segmentManager._paths.size(), 2);
ZNRecord oldZnRec = segmentManager._records.get(0);
ZNRecord newZnRec = segmentManager._records.get(1);
LLCRealtimeSegmentZKMetadata oldMetadata = new LLCRealtimeSegmentZKMetadata(oldZnRec);
LLCRealtimeSegmentZKMetadata newMetadata = new LLCRealtimeSegmentZKMetadata(newZnRec);
LLCSegmentName oldSegmentName = new LLCSegmentName(oldMetadata.getSegmentName());
LLCSegmentName newSegmentName = new LLCSegmentName(newMetadata.getSegmentName());
// Assert on propertystore entries
Assert.assertEquals(oldSegmentName.getSegmentName(), committingSegmentMetadata.getSegmentName());
Assert.assertEquals(newSegmentName.getPartitionId(), oldSegmentName.getPartitionId());
Assert.assertEquals(newSegmentName.getSequenceNumber(), oldSegmentName.getSequenceNumber() + 1);
Assert.assertEquals(oldMetadata.getStatus(), CommonConstants.Segment.Realtime.Status.DONE);
Assert.assertEquals(newMetadata.getStatus(), CommonConstants.Segment.Realtime.Status.IN_PROGRESS);
Assert.assertNotNull(oldMetadata.getDownloadUrl());
Assert.assertEquals(Long.valueOf(oldMetadata.getCrc()), Long.valueOf(FakePinotLLCRealtimeSegmentManager.CRC));
Assert.assertEquals(oldMetadata.getStartTime(), FakePinotLLCRealtimeSegmentManager.INTERVAL.getStartMillis());
Assert.assertEquals(oldMetadata.getEndTime(), FakePinotLLCRealtimeSegmentManager.INTERVAL.getEndMillis());
Assert.assertEquals(oldMetadata.getTotalRawDocs(), FakePinotLLCRealtimeSegmentManager.NUM_DOCS);
Assert.assertEquals(oldMetadata.getIndexVersion(), FakePinotLLCRealtimeSegmentManager.SEGMENT_VERSION);
}
use of com.linkedin.pinot.common.utils.LLCSegmentName in project pinot by linkedin.
the class PinotLLCRealtimeSegmentManagerTest method testCompleteCommittingSegments.
@Test
public void testCompleteCommittingSegments() throws Exception {
// Run multiple times randomizing the situation.
for (int i = 0; i < 100; i++) {
final List<ZNRecord> existingSegmentMetadata = new ArrayList<>(64);
final int nPartitions = 16;
final long seed = new Random().nextLong();
Random random = new Random(seed);
final int maxSeq = 10;
final long now = System.currentTimeMillis();
final String tableName = "table";
final String realtimeTableName = TableNameBuilder.REALTIME_TABLE_NAME_BUILDER.forTable(tableName);
final IdealState idealState = PinotTableIdealStateBuilder.buildEmptyKafkaConsumerRealtimeIdealStateFor(realtimeTableName, 19);
int nIncompleteCommits = 0;
final String topic = "someTopic";
final int nInstances = 5;
final int nReplicas = 3;
List<String> instances = getInstanceList(nInstances);
final String startOffset = KAFKA_OFFSET;
FakePinotLLCRealtimeSegmentManager segmentManager = new FakePinotLLCRealtimeSegmentManager(false, null);
segmentManager.setupHelixEntries(topic, realtimeTableName, nPartitions, instances, nReplicas, startOffset, DUMMY_HOST, idealState, false, 10000);
ZNRecord partitionAssignment = segmentManager.getKafkaPartitionAssignment(realtimeTableName);
for (int p = 0; p < nPartitions; p++) {
// Current segment sequence ID for that partition
int curSeq = random.nextInt(maxSeq);
if (curSeq == 0) {
curSeq++;
}
boolean incomplete = false;
if (random.nextBoolean()) {
incomplete = true;
}
for (int s = 0; s < curSeq; s++) {
LLCSegmentName segmentName = new LLCSegmentName(tableName, p, s, now);
String segNameStr = segmentName.getSegmentName();
String state = PinotHelixSegmentOnlineOfflineStateModelGenerator.ONLINE_STATE;
CommonConstants.Segment.Realtime.Status status = CommonConstants.Segment.Realtime.Status.DONE;
if (s == curSeq - 1) {
state = PinotHelixSegmentOnlineOfflineStateModelGenerator.CONSUMING_STATE;
if (!incomplete) {
status = CommonConstants.Segment.Realtime.Status.IN_PROGRESS;
}
}
List<String> instancesForThisSeg = partitionAssignment.getListField(Integer.toString(p));
for (String instance : instancesForThisSeg) {
idealState.setPartitionState(segNameStr, instance, state);
}
LLCRealtimeSegmentZKMetadata metadata = new LLCRealtimeSegmentZKMetadata();
metadata.setSegmentName(segNameStr);
metadata.setStatus(status);
existingSegmentMetadata.add(metadata.toZNRecord());
}
// Add an incomplete commit to some of them
if (incomplete) {
nIncompleteCommits++;
LLCSegmentName segmentName = new LLCSegmentName(tableName, p, curSeq, now);
LLCRealtimeSegmentZKMetadata metadata = new LLCRealtimeSegmentZKMetadata();
metadata.setSegmentName(segmentName.getSegmentName());
metadata.setStatus(CommonConstants.Segment.Realtime.Status.DONE);
existingSegmentMetadata.add(metadata.toZNRecord());
}
}
segmentManager._tableIdealState = idealState;
segmentManager._existingSegmentMetadata = existingSegmentMetadata;
segmentManager.completeCommittingSegments(TableNameBuilder.REALTIME_TABLE_NAME_BUILDER.forTable(tableName));
Assert.assertEquals(segmentManager._nCallsToUpdateHelix, nIncompleteCommits, "Failed with seed " + seed);
}
}
use of com.linkedin.pinot.common.utils.LLCSegmentName in project pinot by linkedin.
the class SegmentCompletionTest method testStoppedConsumeDuringCompletion.
@Test
public void testStoppedConsumeDuringCompletion() throws Exception {
SegmentCompletionProtocol.Response response;
Request.Params params;
final String reason = "IAmLazy";
// s1 sends offset of 20, gets HOLD at t = 5s;
segmentCompletionMgr._secconds = 5;
params = new Request.Params().withInstanceId(s1).withOffset(s1Offset).withSegmentName(segmentNameStr);
response = segmentCompletionMgr.segmentConsumed(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.HOLD);
// s2 sends offset of 40, gets HOLD
segmentCompletionMgr._secconds += 1;
params = new Request.Params().withInstanceId(s2).withOffset(s2Offset).withSegmentName(segmentNameStr);
response = segmentCompletionMgr.segmentConsumed(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.HOLD);
// s3 sends offset of 30, gets catchup to 40
segmentCompletionMgr._secconds += 1;
params = new Request.Params().withInstanceId(s3).withOffset(s3Offset).withSegmentName(segmentNameStr).withReason(reason);
response = segmentCompletionMgr.segmentStoppedConsuming(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.PROCESSED);
Assert.assertEquals(new LLCSegmentName(segmentNameStr), segmentManager._stoppedSegmentName);
Assert.assertEquals(s3, segmentManager._stoppedInstance);
segmentManager._stoppedSegmentName = null;
segmentManager._stoppedInstance = null;
// Now s1 comes back, and is asked to catchup.
segmentCompletionMgr._secconds += 1;
params = new Request.Params().withInstanceId(s1).withOffset(s1Offset).withSegmentName(segmentNameStr);
response = segmentCompletionMgr.segmentConsumed(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.CATCH_UP);
// s2 is asked to commit.
segmentCompletionMgr._secconds += 1;
params = new Request.Params().withInstanceId(s2).withOffset(s2Offset).withSegmentName(segmentNameStr);
response = segmentCompletionMgr.segmentConsumed(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.COMMIT);
// s3 comes back with new caught up offset, it should get a HOLD, since commit is not done yet.
segmentCompletionMgr._secconds += 1;
params = new Request.Params().withInstanceId(s3).withOffset(s2Offset).withSegmentName(segmentNameStr);
response = segmentCompletionMgr.segmentConsumed(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.HOLD);
// s2 executes a succesful commit
segmentCompletionMgr._secconds += 1;
params = new Request.Params().withInstanceId(s2).withOffset(s2Offset).withSegmentName(segmentNameStr);
response = segmentCompletionMgr.segmentCommitStart(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.COMMIT_CONTINUE);
segmentCompletionMgr._secconds += 5;
params = new Request.Params().withInstanceId(s2).withOffset(s2Offset).withSegmentName(segmentNameStr);
response = segmentCompletionMgr.segmentCommitEnd(params, true);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.COMMIT_SUCCESS);
// Now the FSM should have disappeared from the map
Assert.assertFalse(fsmMap.containsKey(segmentNameStr));
// Now if s3 or s1 come back, they are asked to keep the segment they have.
segmentCompletionMgr._secconds += 1;
params = new Request.Params().withInstanceId(s2).withOffset(s2Offset).withSegmentName(segmentNameStr);
response = segmentCompletionMgr.segmentConsumed(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.KEEP);
// And the FSM should be removed.
Assert.assertFalse(fsmMap.containsKey(segmentNameStr));
}
use of com.linkedin.pinot.common.utils.LLCSegmentName in project pinot by linkedin.
the class SegmentCompletionTest method testHappyPathAfterStoppedConsuming.
// s2 sends stoppedConsuming message, but then may have gotten restarted, so eventually we complete the segment.
@Test
public void testHappyPathAfterStoppedConsuming() throws Exception {
SegmentCompletionProtocol.Response response;
Request.Params params;
segmentCompletionMgr._secconds = 5;
params = new Request.Params().withInstanceId(s2).withOffset(s2Offset).withSegmentName(segmentNameStr).withReason("some reason");
response = segmentCompletionMgr.segmentStoppedConsuming(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.PROCESSED);
Assert.assertEquals(new LLCSegmentName(segmentNameStr), segmentManager._stoppedSegmentName);
Assert.assertEquals(s2, segmentManager._stoppedInstance);
segmentManager._stoppedSegmentName = null;
segmentManager._stoppedInstance = null;
testHappyPath(6L);
}
use of com.linkedin.pinot.common.utils.LLCSegmentName in project pinot by linkedin.
the class SegmentCompletionTest method testHappyPathSlowCommit.
@Test
public void testHappyPathSlowCommit() throws Exception {
SegmentCompletionProtocol.Response response;
Request.Params params;
// s1 sends offset of 20, gets HOLD at t = 5s;
final long startTime = 5;
final String tableName = new LLCSegmentName(segmentNameStr).getTableName();
Assert.assertNull(commitTimeMap.get(tableName));
segmentCompletionMgr._secconds = startTime;
params = new Request.Params().withInstanceId(s1).withOffset(s1Offset).withSegmentName(segmentNameStr);
response = segmentCompletionMgr.segmentConsumed(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.HOLD);
// s2 sends offset of 40, gets HOLD
segmentCompletionMgr._secconds += 1;
params = new Request.Params().withInstanceId(s2).withOffset(s2Offset).withSegmentName(segmentNameStr);
response = segmentCompletionMgr.segmentConsumed(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.HOLD);
// s3 sends offset of 30, gets catchup to 40
segmentCompletionMgr._secconds += 1;
params = new Request.Params().withInstanceId(s3).withOffset(s3Offset).withSegmentName(segmentNameStr);
response = segmentCompletionMgr.segmentConsumed(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.CATCH_UP);
Assert.assertEquals(response.getOffset(), s2Offset);
// Now s1 comes back, and is asked to catchup.
segmentCompletionMgr._secconds += 1;
params = new Request.Params().withInstanceId(s1).withOffset(s1Offset).withSegmentName(segmentNameStr);
response = segmentCompletionMgr.segmentConsumed(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.CATCH_UP);
// s2 is asked to commit.
segmentCompletionMgr._secconds += 1;
params = new Request.Params().withInstanceId(s2).withOffset(s2Offset).withSegmentName(segmentNameStr);
response = segmentCompletionMgr.segmentConsumed(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.COMMIT);
long commitTimeSec = response.getBuildTimeSeconds();
Assert.assertTrue(commitTimeSec > 0);
// Fast forward to one second before commit time, and send a lease renewal request for 20s
segmentCompletionMgr._secconds = startTime + commitTimeSec - 1;
params = new Request.Params().withInstanceId(s2).withOffset(s2Offset).withSegmentName(segmentNameStr).withExtTimeSec(20);
response = segmentCompletionMgr.extendBuildTime(params);
Assert.assertEquals(response.getStatus(), ControllerResponseStatus.PROCESSED);
Assert.assertTrue((fsmMap.containsKey(segmentNameStr)));
// Another lease extension in 19s.
segmentCompletionMgr._secconds += 19;
params = new Request.Params().withInstanceId(s2).withOffset(s2Offset).withSegmentName(segmentNameStr).withExtTimeSec(20);
response = segmentCompletionMgr.extendBuildTime(params);
Assert.assertEquals(response.getStatus(), ControllerResponseStatus.PROCESSED);
Assert.assertTrue((fsmMap.containsKey(segmentNameStr)));
// Commit in 15s
segmentCompletionMgr._secconds += 15;
params = new Request.Params().withInstanceId(s2).withOffset(s2Offset).withSegmentName(segmentNameStr);
response = segmentCompletionMgr.segmentCommitStart(params);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.COMMIT_CONTINUE);
long commitTimeMs = (segmentCompletionMgr._secconds - startTime) * 1000;
Assert.assertEquals(commitTimeMap.get(tableName).longValue(), commitTimeMs);
segmentCompletionMgr._secconds += 55;
response = segmentCompletionMgr.segmentCommitEnd(params, true);
Assert.assertEquals(response.getStatus(), SegmentCompletionProtocol.ControllerResponseStatus.COMMIT_SUCCESS);
// now FSM should be out of the map.
Assert.assertFalse((fsmMap.containsKey(segmentNameStr)));
}
Aggregations