use of org.opendaylight.yangtools.concepts.Identifier in project controller by opendaylight.
the class MessageSlicer method onMessageSliceReply.
private boolean onMessageSliceReply(final MessageSliceReply reply) {
final Identifier identifier = reply.getIdentifier();
if (!(identifier instanceof MessageSliceIdentifier) || ((MessageSliceIdentifier) identifier).getSlicerId() != id) {
return false;
}
final SlicedMessageState<ActorRef> state = stateCache.getIfPresent(identifier);
if (state == null) {
LOG.warn("{}: SlicedMessageState not found for {}", logContext, reply);
reply.getSendTo().tell(new AbortSlicing(identifier), ActorRef.noSender());
return true;
}
synchronized (state) {
try {
final Optional<MessageSliceException> failure = reply.getFailure();
if (failure.isPresent()) {
LOG.warn("{}: Received failed {}", logContext, reply);
processMessageSliceException(failure.get(), state, reply.getSendTo());
return true;
}
if (state.getCurrentSliceIndex() != reply.getSliceIndex()) {
LOG.warn("{}: Slice index {} in {} does not match expected index {}", logContext, reply.getSliceIndex(), reply, state.getCurrentSliceIndex());
reply.getSendTo().tell(new AbortSlicing(identifier), ActorRef.noSender());
possiblyRetrySlicing(state, reply.getSendTo());
return true;
}
if (state.isLastSlice(reply.getSliceIndex())) {
LOG.debug("{}: Received last slice reply for {}", logContext, identifier);
removeState(identifier);
} else {
final MessageSlice nextSlice = getNextSliceMessage(state);
LOG.debug("{}: Sending next slice: {}", logContext, nextSlice);
reply.getSendTo().tell(nextSlice, ActorRef.noSender());
}
} catch (IOException e) {
LOG.warn("{}: Error processing {}", logContext, reply, e);
fail(state, e);
}
}
return true;
}
use of org.opendaylight.yangtools.concepts.Identifier in project controller by opendaylight.
the class LeaderTest method testReplicationWithPayloadSizeThatExceedsThreshold.
@Test
public void testReplicationWithPayloadSizeThatExceedsThreshold() {
logStart("testReplicationWithPayloadSizeThatExceedsThreshold");
final int serializedSize = SerializationUtils.serialize(new AppendEntries(1, LEADER_ID, -1, -1, Arrays.asList(new SimpleReplicatedLogEntry(0, 1, new MockRaftActorContext.MockPayload("large"))), 0, -1, (short) 0)).length;
final MockRaftActorContext.MockPayload largePayload = new MockRaftActorContext.MockPayload("large", serializedSize);
MockRaftActorContext leaderActorContext = createActorContextWithFollower();
((DefaultConfigParamsImpl) leaderActorContext.getConfigParams()).setHeartBeatInterval(new FiniteDuration(300, TimeUnit.MILLISECONDS));
((DefaultConfigParamsImpl) leaderActorContext.getConfigParams()).setSnapshotChunkSize(serializedSize - 50);
leaderActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().build());
leaderActorContext.setCommitIndex(-1);
leaderActorContext.setLastApplied(-1);
leader = new Leader(leaderActorContext);
leaderActorContext.setCurrentBehavior(leader);
// Send initial heartbeat reply so follower is marked active
MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
leader.handleMessage(followerActor, new AppendEntriesReply(FOLLOWER_ID, -1, true, -1, -1, (short) 0));
MessageCollectorActor.clearMessages(followerActor);
// Send normal payload first to prime commit index.
final long term = leaderActorContext.getTermInformation().getCurrentTerm();
sendReplicate(leaderActorContext, term, 0);
AppendEntries appendEntries = MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
assertEquals("Entries size", 1, appendEntries.getEntries().size());
assertEquals("Entry getIndex", 0, appendEntries.getEntries().get(0).getIndex());
leader.handleMessage(followerActor, new AppendEntriesReply(FOLLOWER_ID, term, true, 0, term, (short) 0));
assertEquals("getCommitIndex", 0, leaderActorContext.getCommitIndex());
MessageCollectorActor.clearMessages(followerActor);
// Now send a large payload that exceeds the maximum size for a single AppendEntries - it should be sliced.
sendReplicate(leaderActorContext, term, 1, largePayload);
MessageSlice messageSlice = MessageCollectorActor.expectFirstMatching(followerActor, MessageSlice.class);
assertEquals("getSliceIndex", 1, messageSlice.getSliceIndex());
assertEquals("getTotalSlices", 2, messageSlice.getTotalSlices());
final Identifier slicingId = messageSlice.getIdentifier();
appendEntries = MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
assertEquals("getPrevLogIndex", 0, appendEntries.getPrevLogIndex());
assertEquals("getPrevLogTerm", term, appendEntries.getPrevLogTerm());
assertEquals("getLeaderCommit", -1, appendEntries.getLeaderCommit());
assertEquals("Entries size", 0, appendEntries.getEntries().size());
MessageCollectorActor.clearMessages(followerActor);
// Initiate a heartbeat - it should send an empty AppendEntries since slicing is in progress.
// Sleep for the heartbeat interval so AppendEntries is sent.
Uninterruptibles.sleepUninterruptibly(leaderActorContext.getConfigParams().getHeartBeatInterval().toMillis(), TimeUnit.MILLISECONDS);
leader.handleMessage(leaderActor, SendHeartBeat.INSTANCE);
appendEntries = MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
assertEquals("getLeaderCommit", -1, appendEntries.getLeaderCommit());
assertEquals("Entries size", 0, appendEntries.getEntries().size());
MessageCollectorActor.clearMessages(followerActor);
// Simulate the MessageSliceReply's and AppendEntriesReply from the follower.
leader.handleMessage(followerActor, MessageSliceReply.success(slicingId, 1, followerActor));
messageSlice = MessageCollectorActor.expectFirstMatching(followerActor, MessageSlice.class);
assertEquals("getSliceIndex", 2, messageSlice.getSliceIndex());
leader.handleMessage(followerActor, MessageSliceReply.success(slicingId, 2, followerActor));
leader.handleMessage(followerActor, new AppendEntriesReply(FOLLOWER_ID, term, true, 1, term, (short) 0));
MessageCollectorActor.clearMessages(followerActor);
// Send another normal payload.
sendReplicate(leaderActorContext, term, 2);
appendEntries = MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
assertEquals("Entries size", 1, appendEntries.getEntries().size());
assertEquals("Entry getIndex", 2, appendEntries.getEntries().get(0).getIndex());
assertEquals("getLeaderCommit", 1, appendEntries.getLeaderCommit());
}
use of org.opendaylight.yangtools.concepts.Identifier in project controller by opendaylight.
the class AbstractRaftActorIntegrationTest method verifyApplyState.
protected void verifyApplyState(final ApplyState applyState, final ActorRef expClientActor, final String expId, final long expTerm, final long expIndex, final Payload payload) {
assertEquals("ApplyState getClientActor", expClientActor, applyState.getClientActor());
final Identifier id = expId == null ? null : new MockIdentifier(expId);
assertEquals("ApplyState getIdentifier", id, applyState.getIdentifier());
ReplicatedLogEntry replicatedLogEntry = applyState.getReplicatedLogEntry();
verifyReplicatedLogEntry(replicatedLogEntry, expTerm, expIndex, payload);
}
use of org.opendaylight.yangtools.concepts.Identifier in project controller by opendaylight.
the class MessageAssembler method processMessageSliceForState.
private void processMessageSliceForState(final MessageSlice messageSlice, final AssembledMessageState state, final ActorRef sendTo) {
final Identifier identifier = messageSlice.getIdentifier();
final ActorRef replyTo = messageSlice.getReplyTo();
Object reAssembledMessage = null;
synchronized (state) {
final int sliceIndex = messageSlice.getSliceIndex();
try {
final MessageSliceReply successReply = MessageSliceReply.success(identifier, sliceIndex, sendTo);
if (state.addSlice(sliceIndex, messageSlice.getData(), messageSlice.getLastSliceHashCode())) {
LOG.debug("{}: Received last slice for {}", logContext, identifier);
reAssembledMessage = reAssembleMessage(state);
replyTo.tell(successReply, ActorRef.noSender());
removeState(identifier);
} else {
LOG.debug("{}: Added slice for {} - expecting more", logContext, identifier);
replyTo.tell(successReply, ActorRef.noSender());
}
} catch (MessageSliceException e) {
LOG.warn("{}: Error processing {}", logContext, messageSlice, e);
replyTo.tell(MessageSliceReply.failed(identifier, e, sendTo), ActorRef.noSender());
removeState(identifier);
}
}
if (reAssembledMessage != null) {
LOG.debug("{}: Notifying callback of re-assembled message {}", logContext, reAssembledMessage);
assembledMessageCallback.accept(reAssembledMessage, replyTo);
}
}
use of org.opendaylight.yangtools.concepts.Identifier in project controller by opendaylight.
the class MessageAssembler method onMessageSlice.
private void onMessageSlice(final MessageSlice messageSlice, final ActorRef sendTo) {
final Identifier identifier = messageSlice.getIdentifier();
try {
final AssembledMessageState state = stateCache.get(identifier, () -> createState(messageSlice));
processMessageSliceForState(messageSlice, state, sendTo);
} catch (ExecutionException e) {
final MessageSliceException messageSliceEx;
final Throwable cause = e.getCause();
if (cause instanceof MessageSliceException) {
messageSliceEx = (MessageSliceException) cause;
} else {
messageSliceEx = new MessageSliceException(String.format("Error creating state for identifier %s", identifier), cause);
}
messageSlice.getReplyTo().tell(MessageSliceReply.failed(identifier, messageSliceEx, sendTo), ActorRef.noSender());
}
}
Aggregations