use of org.apache.cassandra.simulator.systems.SimulatedAction.Kind.MESSAGE in project cassandra by apache.
the class SimulatedAction method applyToMessage.
Action applyToMessage(IInvokableInstance from, IInvokableInstance to, IMessage message) {
Executor executor = to.executorFor(message.verb());
if (executor instanceof ImmediateExecutor)
executor = to.executor();
InterceptedExecution.InterceptedTaskExecution task = new InterceptedRunnableExecution((InterceptingExecutor) executor, () -> to.receiveMessageWithInvokingThread(message));
Verb verb = Verb.fromId(message.verb());
Modifiers self = verbModifiers.getOrDefault(verb, NONE);
int fromNum = from.config().num();
int toNum = to.config().num();
Deliver deliver;
if (is(Modifier.RELIABLE) || self.is(Modifier.RELIABLE))
deliver = DELIVER;
else
deliver = simulated.futureScheduler.shouldDeliver(fromNum, toNum);
Action action;
switch(deliver) {
default:
throw new AssertionError();
case DELIVER:
{
Object description = lazy(() -> String.format("%s(%d) from %s to %s", Verb.fromId(message.verb()), message.id(), message.from(), to.broadcastAddress()));
OrderOn orderOn = task.executor.orderAppliesAfterScheduling();
action = applyTo(description, MESSAGE, orderOn, self, verb, task);
action.setDeadline(simulated.futureScheduler.messageDeadlineNanos(fromNum, toNum));
break;
}
case FAILURE:
case TIMEOUT:
{
task.cancel();
self = DROP.with(self);
InetSocketAddress failedOn;
IInvokableInstance notify;
if (verb.isResponse()) {
failedOn = from.broadcastAddress();
notify = to;
} else {
failedOn = to.broadcastAddress();
notify = from;
}
InterceptedExecution.InterceptedTaskExecution failTask = new InterceptedRunnableExecution((InterceptingExecutor) notify.executorFor(verb.id), () -> notify.unsafeApplyOnThisThread((socketAddress, id, isTimeout) -> {
InetAddressAndPort address = InetAddressAndPort.getByAddress(socketAddress);
RequestCallbacks.CallbackInfo callback = instance().callbacks.remove(id, address);
if (callback != null) {
RequestCallback<?> invokeOn = (RequestCallback<?>) callback.callback;
RequestFailureReason reason = isTimeout ? RequestFailureReason.TIMEOUT : RequestFailureReason.UNKNOWN;
invokeOn.onFailure(address, reason);
}
return null;
}, failedOn, message.id(), deliver == TIMEOUT));
Object description = (lazy(() -> String.format("Report Timeout of %s(%d) from %s to %s", Verb.fromId(message.verb()), message.id(), failedOn, notify.broadcastAddress())));
OrderOn orderOn = failTask.executor.orderAppliesAfterScheduling();
action = applyTo(description, MESSAGE, orderOn, self, failTask);
switch(deliver) {
default:
throw new AssertionError();
case TIMEOUT:
long expiresAfterNanos = from.unsafeApplyOnThisThread(id -> Verb.fromId(id).expiresAfterNanos(), (verb.isResponse() ? forVerb : verb).id);
action.setDeadline(simulated.futureScheduler.messageTimeoutNanos(expiresAfterNanos));
break;
case FAILURE:
action.setDeadline(simulated.futureScheduler.messageFailureNanos(toNum, fromNum));
break;
}
break;
}
}
return action;
}
Aggregations